mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
Merge branch 'dev' into dev
This commit is contained in:
commit
524c57d4fc
11 changed files with 556 additions and 9 deletions
|
@ -11,6 +11,8 @@ import "./providers/2embed";
|
||||||
import "./providers/sflix";
|
import "./providers/sflix";
|
||||||
import "./providers/gomovies";
|
import "./providers/gomovies";
|
||||||
import "./providers/kissasian";
|
import "./providers/kissasian";
|
||||||
|
import "./providers/streamflix";
|
||||||
|
import "./providers/remotestream";
|
||||||
|
|
||||||
// embeds
|
// embeds
|
||||||
import "./embeds/streamm4u";
|
import "./embeds/streamm4u";
|
||||||
|
|
49
src/backend/providers/remotestream.ts
Normal file
49
src/backend/providers/remotestream.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { mwFetch } from "@/backend/helpers/fetch";
|
||||||
|
import { registerProvider } from "@/backend/helpers/register";
|
||||||
|
import { MWStreamQuality, MWStreamType } from "@/backend/helpers/streams";
|
||||||
|
import { MWMediaType } from "@/backend/metadata/types";
|
||||||
|
|
||||||
|
const remotestreamBase = `https://fsa.remotestre.am`;
|
||||||
|
|
||||||
|
registerProvider({
|
||||||
|
id: "remotestream",
|
||||||
|
displayName: "Remote Stream",
|
||||||
|
disabled: false,
|
||||||
|
rank: 55,
|
||||||
|
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||||
|
|
||||||
|
async scrape({ media, episode, progress }) {
|
||||||
|
if (!this.type.includes(media.meta.type)) {
|
||||||
|
throw new Error("Unsupported type");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(30);
|
||||||
|
const type = media.meta.type === MWMediaType.MOVIE ? "Movies" : "Shows";
|
||||||
|
let playlistLink = `${remotestreamBase}/${type}/${media.tmdbId}`;
|
||||||
|
|
||||||
|
if (media.meta.type === MWMediaType.SERIES) {
|
||||||
|
const seasonNumber = media.meta.seasonData.number;
|
||||||
|
const episodeNumber = media.meta.seasonData.episodes.find(
|
||||||
|
(e) => e.id === episode
|
||||||
|
)?.number;
|
||||||
|
|
||||||
|
playlistLink += `/${seasonNumber}/${episodeNumber}/${episodeNumber}.m3u8`;
|
||||||
|
} else {
|
||||||
|
playlistLink += `/${media.tmdbId}.m3u8`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const streamRes = await mwFetch<Blob>(playlistLink);
|
||||||
|
if (streamRes.type !== "application/x-mpegurl")
|
||||||
|
throw new Error("No watchable item found");
|
||||||
|
progress(90);
|
||||||
|
return {
|
||||||
|
embeds: [],
|
||||||
|
stream: {
|
||||||
|
streamUrl: playlistLink,
|
||||||
|
quality: MWStreamQuality.QUNKNOWN,
|
||||||
|
type: MWStreamType.HLS,
|
||||||
|
captions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
70
src/backend/providers/streamflix.ts
Normal file
70
src/backend/providers/streamflix.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import { proxiedFetch } from "@/backend/helpers/fetch";
|
||||||
|
import { registerProvider } from "@/backend/helpers/register";
|
||||||
|
import {
|
||||||
|
MWCaptionType,
|
||||||
|
MWStreamQuality,
|
||||||
|
MWStreamType,
|
||||||
|
} from "@/backend/helpers/streams";
|
||||||
|
import { MWMediaType } from "@/backend/metadata/types";
|
||||||
|
|
||||||
|
const streamflixBase = "https://us-west2-compute-proxied.streamflix.one";
|
||||||
|
|
||||||
|
const qualityMap: Record<number, MWStreamQuality> = {
|
||||||
|
360: MWStreamQuality.Q360P,
|
||||||
|
540: MWStreamQuality.Q540P,
|
||||||
|
480: MWStreamQuality.Q480P,
|
||||||
|
720: MWStreamQuality.Q720P,
|
||||||
|
1080: MWStreamQuality.Q1080P,
|
||||||
|
};
|
||||||
|
|
||||||
|
registerProvider({
|
||||||
|
id: "streamflix",
|
||||||
|
displayName: "StreamFlix",
|
||||||
|
disabled: false,
|
||||||
|
rank: 69,
|
||||||
|
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||||
|
|
||||||
|
async scrape({ media, episode, progress }) {
|
||||||
|
if (!this.type.includes(media.meta.type)) {
|
||||||
|
throw new Error("Unsupported type");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(30);
|
||||||
|
const type = media.meta.type === MWMediaType.MOVIE ? "movies" : "tv";
|
||||||
|
let seasonNumber: number | undefined;
|
||||||
|
let episodeNumber: number | undefined;
|
||||||
|
|
||||||
|
if (media.meta.type === MWMediaType.SERIES) {
|
||||||
|
// can't do type === "tv" here :(
|
||||||
|
seasonNumber = media.meta.seasonData.number;
|
||||||
|
episodeNumber = media.meta.seasonData.episodes.find(
|
||||||
|
(e: any) => e.id === episode
|
||||||
|
)?.number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const streamRes = await proxiedFetch<any>(`/api/player/${type}`, {
|
||||||
|
baseURL: streamflixBase,
|
||||||
|
params: {
|
||||||
|
id: media.tmdbId,
|
||||||
|
s: seasonNumber,
|
||||||
|
e: episodeNumber,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!streamRes.headers.Referer) throw new Error("No watchable item found");
|
||||||
|
progress(90);
|
||||||
|
return {
|
||||||
|
embeds: [],
|
||||||
|
stream: {
|
||||||
|
streamUrl: streamRes.sources[0].url,
|
||||||
|
quality: qualityMap[streamRes.sources[0].quality],
|
||||||
|
type: MWStreamType.HLS,
|
||||||
|
captions: streamRes.subtitles.map((s: Record<string, any>) => ({
|
||||||
|
needsProxy: true,
|
||||||
|
url: s.url,
|
||||||
|
type: MWCaptionType.VTT,
|
||||||
|
langIso: s.lang,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -154,7 +154,7 @@ export const FloatingCardView = {
|
||||||
className="flex cursor-pointer items-center space-x-2 transition-colors duration-200 hover:text-white"
|
className="flex cursor-pointer items-center space-x-2 transition-colors duration-200 hover:text-white"
|
||||||
>
|
>
|
||||||
<Icon icon={Icons.X} />
|
<Icon icon={Icons.X} />
|
||||||
<span>Close</span>
|
<span>{t("videoPlayer.popouts.close")}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,21 @@ import cs from "./locales/cs/translation.json";
|
||||||
import de from "./locales/de/translation.json";
|
import de from "./locales/de/translation.json";
|
||||||
import en from "./locales/en/translation.json";
|
import en from "./locales/en/translation.json";
|
||||||
import fr from "./locales/fr/translation.json";
|
import fr from "./locales/fr/translation.json";
|
||||||
|
import it from "./locales/it/translation.json";
|
||||||
import nl from "./locales/nl/translation.json";
|
import nl from "./locales/nl/translation.json";
|
||||||
import pirate from "./locales/pirate/translation.json";
|
import pirate from "./locales/pirate/translation.json";
|
||||||
|
import pl from "./locales/pl/translation.json";
|
||||||
import tr from "./locales/tr/translation.json";
|
import tr from "./locales/tr/translation.json";
|
||||||
|
import vi from "./locales/vi/translation.json";
|
||||||
import zh from "./locales/zh/translation.json";
|
import zh from "./locales/zh/translation.json";
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
en: {
|
en: {
|
||||||
translation: en,
|
translation: en,
|
||||||
},
|
},
|
||||||
|
it: {
|
||||||
|
translation: it,
|
||||||
|
},
|
||||||
nl: {
|
nl: {
|
||||||
translation: nl,
|
translation: nl,
|
||||||
},
|
},
|
||||||
|
@ -37,6 +43,12 @@ const locales = {
|
||||||
pirate: {
|
pirate: {
|
||||||
translation: pirate,
|
translation: pirate,
|
||||||
},
|
},
|
||||||
|
vi: {
|
||||||
|
translation: vi,
|
||||||
|
},
|
||||||
|
pl: {
|
||||||
|
translation: pl,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
i18n
|
i18n
|
||||||
// pass the i18n instance to react-i18next.
|
// pass the i18n instance to react-i18next.
|
||||||
|
|
|
@ -71,7 +71,16 @@
|
||||||
"popouts": {
|
"popouts": {
|
||||||
"back": "Go back",
|
"back": "Go back",
|
||||||
"sources": "Sources",
|
"sources": "Sources",
|
||||||
"seasons": "Seasons",
|
"close": "Close",
|
||||||
|
"seasons": {
|
||||||
|
"title":"Seasons",
|
||||||
|
"other": "Other seasons",
|
||||||
|
"noSeason": "No season"
|
||||||
|
},
|
||||||
|
"episodes": {
|
||||||
|
"unknown": "Unknown episode",
|
||||||
|
"noEpisode": "No episode"
|
||||||
|
},
|
||||||
"captions": "Captions",
|
"captions": "Captions",
|
||||||
"playbackSpeed": "Playback speed",
|
"playbackSpeed": "Playback speed",
|
||||||
"customPlaybackSpeed": "Custom playback speed",
|
"customPlaybackSpeed": "Custom playback speed",
|
||||||
|
|
128
src/setup/locales/it/translation.json
Normal file
128
src/setup/locales/it/translation.json
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"name": "movie-web"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"loading_series": "Recupero delle tue serie preferite...",
|
||||||
|
"loading_movie": "Recupero dei tuoi film preferiti...",
|
||||||
|
"loading": "Caricamento...",
|
||||||
|
"allResults": "Ecco tutto ciò che abbiamo!",
|
||||||
|
"noResults": "Non abbiamo trovato nulla!",
|
||||||
|
"allFailed": "Impossibile trovare i media, riprova!",
|
||||||
|
"headingTitle": "Risultati della ricerca",
|
||||||
|
"bookmarks": "Segnalibri",
|
||||||
|
"continueWatching": "Continua a guardare",
|
||||||
|
"title": "Cosa vuoi guardare?",
|
||||||
|
"placeholder": "Cosa vuoi guardare?"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"movie": "Film",
|
||||||
|
"series": "Serie",
|
||||||
|
"stopEditing": "Interrompi modifica",
|
||||||
|
"errors": {
|
||||||
|
"genericTitle": "Ops, qualcosa si è rotto!",
|
||||||
|
"failedMeta": "Caricamento dei metadati non riuscito",
|
||||||
|
"mediaFailed": "Impossibile richiedere il media che hai richiesto, controlla la tua connessione internet e riprova.",
|
||||||
|
"videoFailed": "Si è verificato un errore durante la riproduzione del video che hai richiesto. Se ciò continua a accadere, segnala il problema sul <0>server Discord</0> o su <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"seasons": {
|
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}"
|
||||||
|
},
|
||||||
|
"notFound": {
|
||||||
|
"genericTitle": "Non trovato",
|
||||||
|
"backArrow": "Torna alla home",
|
||||||
|
"media": {
|
||||||
|
"title": "Impossibile trovare quel media",
|
||||||
|
"description": "Non siamo riusciti a trovare il media richiesto. È stato rimosso o hai manomesso l'URL."
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"title": "Questo provider è stato disabilitato",
|
||||||
|
"description": "Abbiamo riscontrato problemi con il provider o era troppo instabile da utilizzare, quindi abbiamo dovuto disabilitarlo."
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"title": "Impossibile trovare quella pagina",
|
||||||
|
"description": "Abbiamo cercato ovunque: sotto i bidoni, nell'armadio, dietro il proxy, ma alla fine non siamo riusciti a trovare la pagina che stai cercando."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"searchBar": {
|
||||||
|
"movie": "Film",
|
||||||
|
"series": "Serie",
|
||||||
|
"Search": "Cerca"
|
||||||
|
},
|
||||||
|
"videoPlayer": {
|
||||||
|
"findingBestVideo": "Ricerca del miglior video per te",
|
||||||
|
"noVideos": "Ops, non è stato possibile trovare alcun video per te",
|
||||||
|
"loading": "Caricamento...",
|
||||||
|
"backToHome": "Torna alla home",
|
||||||
|
"backToHomeShort": "Indietro",
|
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}",
|
||||||
|
"timeLeft": "{{timeLeft}} rimanente",
|
||||||
|
"finishAt": "Fine alle {{timeFinished, datetime}}",
|
||||||
|
"buttons": {
|
||||||
|
"episodes": "Episodi",
|
||||||
|
"source": "Fonte",
|
||||||
|
"captions": "Sottotitoli",
|
||||||
|
"download": "Download",
|
||||||
|
"settings": "Impostazioni",
|
||||||
|
"pictureInPicture": "Picture in Picture",
|
||||||
|
"playbackSpeed": "Velocità di riproduzione"
|
||||||
|
},
|
||||||
|
"popouts": {
|
||||||
|
"back": "Torna indietro",
|
||||||
|
"sources": "Fonti",
|
||||||
|
"seasons": "Stagioni",
|
||||||
|
"captions": "Sottotitoli",
|
||||||
|
"playbackSpeed": "Velocità di riproduzione",
|
||||||
|
"customPlaybackSpeed": "Velocità di riproduzione personalizzata",
|
||||||
|
"captionPreferences": {
|
||||||
|
"title": "Personalizza",
|
||||||
|
"delay": "Ritardo",
|
||||||
|
"fontSize": "Dimensione carattere",
|
||||||
|
"opacity": "Opacità",
|
||||||
|
"color": "Colore"
|
||||||
|
},
|
||||||
|
"episode": "E{{index}} - {{title}}",
|
||||||
|
"noCaptions": "Nessun sottotitolo",
|
||||||
|
"linkedCaptions": "Sottotitoli collegati",
|
||||||
|
"customCaption": "Sottotitolo personalizzato",
|
||||||
|
"uploadCustomCaption": "Carica sottotitolo",
|
||||||
|
"noEmbeds": "Nessun embed è stato trovato per questa fonte",
|
||||||
|
|
||||||
|
"errors": {
|
||||||
|
"loadingWentWong": "Si è verificato un problema durante il caricamento degli episodi per {{seasonTitle}}",
|
||||||
|
"embedsError": "Si è verificato un problema durante il caricamento degli embed per questa cosa che ti piace"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"sources": "Quale provider desideri utilizzare?",
|
||||||
|
"embeds": "Scegli quale video visualizzare",
|
||||||
|
"seasons": "Scegli quale stagione vuoi guardare",
|
||||||
|
"episode": "Scegli un episodio",
|
||||||
|
"captions": "Scegli una lingua per i sottotitoli",
|
||||||
|
"captionPreferences": "Personalizza l'aspetto dei sottotitoli",
|
||||||
|
"playbackSpeed": "Cambia la velocità di riproduzione"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fatalError": "Il lettore video ha riscontrato un errore fatale, segnalalo sul <0>server Discord</0> o su <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Impostazioni",
|
||||||
|
"language": "Lingua",
|
||||||
|
"captionLanguage": "Lingua dei sottotitoli"
|
||||||
|
},
|
||||||
|
"v3": {
|
||||||
|
"newSiteTitle": "Nuova versione ora disponibile!",
|
||||||
|
"newDomain": "https://movie-web.app",
|
||||||
|
"newDomainText": "movie-web si sposterà presto su un nuovo dominio: <0>https://movie-web.app</0>. Assicurati di aggiornare tutti i tuoi segnalibri poiché <1>il vecchio sito smetterà di funzionare il {{date}}.</1>",
|
||||||
|
"tireless": "Abbiamo lavorato instancabilmente su questo nuovo aggiornamento, speriamo che ti piaccia quello su cui abbiamo lavorato negli ultimi mesi.",
|
||||||
|
"leaveAnnouncement": "Portami lì!"
|
||||||
|
},
|
||||||
|
"casting": {
|
||||||
|
"casting": "Trasmissione su dispositivo in corso..."
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"offline": "Controlla la tua connessione internet"
|
||||||
|
}
|
||||||
|
}
|
137
src/setup/locales/pl/translation.json
Normal file
137
src/setup/locales/pl/translation.json
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"name": "movie-web"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"loading_series": "Szukamy twoich ulubionych seriali...",
|
||||||
|
"loading_movie": "Szukamy twoich ulubionych filmów...",
|
||||||
|
"loading": "Wczytywanie...",
|
||||||
|
"allResults": "To wszystko co mamy!",
|
||||||
|
"noResults": "Nie mogliśmy niczego znaleźć!",
|
||||||
|
"allFailed": "Nie udało się znaleźć mediów, Spróbuj ponownie!",
|
||||||
|
"headingTitle": "Wyniki wyszukiwania",
|
||||||
|
"bookmarks": "Zakładki",
|
||||||
|
"continueWatching": "Kontynuuj oglądanie",
|
||||||
|
"title": "Co chciałbyś obejrzeć?",
|
||||||
|
"placeholder": "Co chciałbyś obejrzeć?"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"movie": "Film",
|
||||||
|
"series": "Serial",
|
||||||
|
"stopEditing": "Zatrzymaj edycje",
|
||||||
|
"errors": {
|
||||||
|
"genericTitle": "Ups, popsuło się!",
|
||||||
|
"failedMeta": "Nie udało się wczytać metadanych",
|
||||||
|
"mediaFailed": "Nie udało nam się zarządać mediów, sprawdź połączenie sieciowe i spróbuj ponownie.",
|
||||||
|
"videoFailed": "Napotkaliśmy błąd podczas odtwarzania rządanego video. Jeśli problem będzie się powtarzać prosimy o zgłoszenie problemu na <0>Serwer Discord</0> lub na <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"seasons": {
|
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}"
|
||||||
|
},
|
||||||
|
"notFound": {
|
||||||
|
"genericTitle": "Nie znaleziono",
|
||||||
|
"backArrow": "Wróć na stronę główną",
|
||||||
|
"media": {
|
||||||
|
"title": "Nie można znaleźć multimediów",
|
||||||
|
"description": "Nie mogliśmy znaleźć rządanych multimediów. Albo zostały usunięte, albo grzebałeś przy adresie URL."
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"title": "Ten dostawca został wyłączony",
|
||||||
|
"description": "Mieliśmy problemy z tym dostawcą, albo był zbyt niestabilny, więc musieliśmy go wyłączyć."
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"title": "Nie można znaleźć tej strony",
|
||||||
|
"description": "Szukaliśmy wszędzie: w koszu, w szafie a nawet w piwnicy, ale nie byliśmy w stanie znaleźć strony której szukasz."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"searchBar": {
|
||||||
|
"movie": "Filmy",
|
||||||
|
"series": "Seriale",
|
||||||
|
"Search": "Szukaj"
|
||||||
|
},
|
||||||
|
"videoPlayer": {
|
||||||
|
"findingBestVideo": "Szukamy najlepszego video dla ciebie",
|
||||||
|
"noVideos": "Oj, Nie mogliśmy znaleźć żadnego video",
|
||||||
|
"loading": "Wczytywanie...",
|
||||||
|
"backToHome": "Wróć na stronę główną",
|
||||||
|
"backToHomeShort": "Wróć",
|
||||||
|
"seasonAndEpisode": "S{{season}} E{{episode}}",
|
||||||
|
"timeLeft": "Pozostało {{timeLeft}}",
|
||||||
|
"finishAt": "Zakończ na {{timeFinished, datetime}}",
|
||||||
|
"buttons": {
|
||||||
|
"episodes": "Odcinki",
|
||||||
|
"source": "Źródło",
|
||||||
|
"captions": "Napisy",
|
||||||
|
"download": "Pobierz",
|
||||||
|
"settings": "Ustawienia",
|
||||||
|
"pictureInPicture": "Obraz w obrazie (PIP)",
|
||||||
|
"playbackSpeed": "Prędkość odtwarzania"
|
||||||
|
},
|
||||||
|
"popouts": {
|
||||||
|
"close": "Zamknąć",
|
||||||
|
"seasons": {
|
||||||
|
"title":"Sezony",
|
||||||
|
"other": "Inne sezony",
|
||||||
|
"noSeason": "Brak sezonu"
|
||||||
|
},
|
||||||
|
"episodes": {
|
||||||
|
"unknown": "Nieznany odcinki",
|
||||||
|
"noEpisode": "Brak odcinki"
|
||||||
|
},
|
||||||
|
"back": "Wróć",
|
||||||
|
"sources": "Źródła",
|
||||||
|
"captions": "Napisy",
|
||||||
|
"playbackSpeed": "Prędkość odtwarzania",
|
||||||
|
"customPlaybackSpeed": "Niestandardowa prędkość odtwarzania",
|
||||||
|
"captionPreferences": {
|
||||||
|
"title": "Personalizuj",
|
||||||
|
"delay": "Opóźnienie",
|
||||||
|
"fontSize": "Rozmiar",
|
||||||
|
"opacity": "Przeźroczystość",
|
||||||
|
"color": "Kolor"
|
||||||
|
},
|
||||||
|
"episode": "E{{index}} - {{title}}",
|
||||||
|
"noCaptions": "Brak napisów",
|
||||||
|
"linkedCaptions": "Załączone napisy",
|
||||||
|
"customCaption": "Napisy niestandardowe",
|
||||||
|
"uploadCustomCaption": "Załącz",
|
||||||
|
"noEmbeds": "Nie znaleziono osadzonych mediów dla tego źródła",
|
||||||
|
|
||||||
|
"errors": {
|
||||||
|
"loadingWentWong": "Coś poszło nie tak {{seasonTitle}}",
|
||||||
|
"embedsError": "Coś poszło nie tak przy wczytywaniu osadzonych mediów"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"sources": "Którego dostawcy chciałbyś używać?",
|
||||||
|
"embeds": "Wybierz, które video chcesz zobaczyć",
|
||||||
|
"seasons": "Wybierz, który sezon chcesz obejrzeć",
|
||||||
|
"episode": "Wybierz odcinek",
|
||||||
|
"captions": "Zmień język napisów",
|
||||||
|
"captionPreferences": "Ustaw napisy, tak jak ci to odpowiada",
|
||||||
|
"playbackSpeed": "Zmień prędkość odtwarzania"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fatalError": "Odtwarzacz napotkał poważny błąd, Prosimy o złoszenie tego na <0>Serwer Discord</0> lub na <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Ustawienia",
|
||||||
|
"language": "Język",
|
||||||
|
"captionLanguage": "Język napisów"
|
||||||
|
},
|
||||||
|
"v3": {
|
||||||
|
"newSiteTitle": "Nowa wersja została wydana!",
|
||||||
|
"newDomain": "https://movie-web.app",
|
||||||
|
"newDomainText": "movie-web przeniesie się wkrótce na nowy adres: <0>https://movie-web.app</0>. Prosimy zaaktualizować swoje zakładki ponieważ <1>stara strona przestanie działać {{date}}.</1>",
|
||||||
|
"tireless": "Pracowaliśmy niestrudzenie nad tą aktualizacją, Mamy nadzieję że będziecie zadowoleni z tego nad czym pracowaliśmy przez ostatnie parę miesięcy.",
|
||||||
|
"leaveAnnouncement": "Zabierz mnie tam!"
|
||||||
|
},
|
||||||
|
"casting": {
|
||||||
|
"casting": "Przesyłanie do urządzenia..."
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"offline": "Sprawdź swoje połączenie sieciowe"
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,16 @@
|
||||||
"popouts": {
|
"popouts": {
|
||||||
"back": "Geri git",
|
"back": "Geri git",
|
||||||
"sources": "Kaynaklar",
|
"sources": "Kaynaklar",
|
||||||
"seasons": "Sezonlar",
|
"close":"Kapat",
|
||||||
|
"seasons": {
|
||||||
|
"title":"Sezonlar",
|
||||||
|
"other": "Diğer sezonlar",
|
||||||
|
"noSeason": "Sezon yok"
|
||||||
|
},
|
||||||
|
"episodes": {
|
||||||
|
"unknown": "Bilinmeyen bölüm",
|
||||||
|
"noEpisode": "Bölüm yok"
|
||||||
|
},
|
||||||
"captions": "Altyazılar",
|
"captions": "Altyazılar",
|
||||||
"playbackSpeed": "Oynatma hızı",
|
"playbackSpeed": "Oynatma hızı",
|
||||||
"customPlaybackSpeed": "Özel oynatma hızı",
|
"customPlaybackSpeed": "Özel oynatma hızı",
|
||||||
|
|
128
src/setup/locales/vi/translation.json
Normal file
128
src/setup/locales/vi/translation.json
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"name": "movie-web"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"loading_series": "Đang tìm chương trình yêu thích của bạn...",
|
||||||
|
"loading_movie": "Đang tìm bộ phim yêu thích của bạn...",
|
||||||
|
"loading": "Đang tải...",
|
||||||
|
"allResults": "Đó là tất cả chúng tôi có!",
|
||||||
|
"noResults": "Chúng tôi không thể tìm thấy gì!",
|
||||||
|
"allFailed": "Không thể tìm thấy nội dung, hãy thử lại!",
|
||||||
|
"headingTitle": "Kết quả tìm kiếm",
|
||||||
|
"bookmarks": "Đánh dấu",
|
||||||
|
"continueWatching": "Tiếp tục xem",
|
||||||
|
"title": "Bạn muốn xem gì?",
|
||||||
|
"placeholder": "Bạn muốn xem gì?"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"movie": "Phim",
|
||||||
|
"series": "Chương trình truyền hình",
|
||||||
|
"stopEditing": "Hãy dừng chỉnh sửa",
|
||||||
|
"errors": {
|
||||||
|
"genericTitle": "Rất tiếc, đã hỏng!",
|
||||||
|
"failedMeta": "Không thể tải meta",
|
||||||
|
"mediaFailed": "Chúng tôi không thể tìm thấy nội dung mà bạn yêu cầu, hãy kiểm tra kết nối internet của bạn và thử lại.",
|
||||||
|
"videoFailed": "Chúng tôi đã gặp lỗi khi phát nội dung mà bạn yêu cầu. Nếu điều này tiếp tục xảy ra, vui lòng báo cáo sự cố trên <0>máy chủ Discord</0> hoặc trên <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"seasons": {
|
||||||
|
"seasonAndEpisode": "M{{season}} T{{episode}}"
|
||||||
|
},
|
||||||
|
"notFound": {
|
||||||
|
"genericTitle": "Không tìm thấy",
|
||||||
|
"backArrow": "Quay lại trang chính",
|
||||||
|
"media": {
|
||||||
|
"title": "Không thể tìm thấy nội dung",
|
||||||
|
"description": "Chúng tôi không thể tìm thấy nội dung mà bạn yêu cầu. Hoặc là nó đã bị xóa, hoặc bạn đã xáo trộn URL"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"title": "Nhà cung cấp này đã bị vô hiệu hóa",
|
||||||
|
"description": "Chúng tôi đã gặp vấn đề với nhà cung cấp hoặc nó quá bất ổn để sử dụng, cho nên chúng tôi đã phải vô hiệu hóa nó."
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"title": "Không thể tìm thấy trang",
|
||||||
|
"description": "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."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"searchBar": {
|
||||||
|
"movie": "Phim",
|
||||||
|
"series": "Chương trình truyền hình",
|
||||||
|
"Search": "Tìm kiếm"
|
||||||
|
},
|
||||||
|
"videoPlayer": {
|
||||||
|
"findingBestVideo": "Đang tìm nội dung tốt nhất cho bạn",
|
||||||
|
"noVideos": "Rất tiếc, không tìm thấy nội dung nào cho bạn",
|
||||||
|
"loading": "Đang tải...",
|
||||||
|
"backToHome": "Quay lại trang chính",
|
||||||
|
"backToHomeShort": "Quay lại",
|
||||||
|
"seasonAndEpisode": "M{{season}} T{{episode}}",
|
||||||
|
"timeLeft": "Còn {{timeLeft}}",
|
||||||
|
"finishAt": "Kết thúc vào {{timeFinished, datetime}}",
|
||||||
|
"buttons": {
|
||||||
|
"episodes": "Tập",
|
||||||
|
"source": "Source",
|
||||||
|
"captions": "Phụ đề",
|
||||||
|
"download": "Tải xuống",
|
||||||
|
"settings": "Cài đặt",
|
||||||
|
"pictureInPicture": "Hình trong hình",
|
||||||
|
"playbackSpeed": "Tốc độ phát"
|
||||||
|
},
|
||||||
|
"popouts": {
|
||||||
|
"back": "Quay lại",
|
||||||
|
"sources": "Nguồn",
|
||||||
|
"seasons": "Mùa",
|
||||||
|
"captions": "Phụ đề",
|
||||||
|
"playbackSpeed": "Tốc độ phát",
|
||||||
|
"customPlaybackSpeed": "Tủy chỉnh tốc độ phát",
|
||||||
|
"captionPreferences": {
|
||||||
|
"title": "Tùy chỉnh",
|
||||||
|
"delay": "Trì hoãn",
|
||||||
|
"fontSize": "Kích cỡ",
|
||||||
|
"opacity": "Độ mờ",
|
||||||
|
"color": "Màu sắc"
|
||||||
|
},
|
||||||
|
"episode": "T{{index}} - {{title}}",
|
||||||
|
"noCaptions": "Không phụ đề",
|
||||||
|
"linkedCaptions": "Phụ đề được liên kết",
|
||||||
|
"customCaption": "Phụ đề tùy chỉnh",
|
||||||
|
"uploadCustomCaption": "Tải phụ đề lên",
|
||||||
|
"noEmbeds": "Không tìm thấy nội dung nhúng nào cho nguồn này",
|
||||||
|
|
||||||
|
"errors": {
|
||||||
|
"loadingWentWong": "Đã xảy ra lỗi khi tải các tập phim cho {{seasonTitle}}",
|
||||||
|
"embedsError": "Đã xảy ra lỗi khi tải nội dung nhúng cho nội dung bạn thích này"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"sources": "Bạn muốn sử dụng nhà cung cấp nào?",
|
||||||
|
"embeds": "Chọn video để xem",
|
||||||
|
"seasons": "Chọn mùa bạn muốn xem",
|
||||||
|
"episode": "Chọn một tập",
|
||||||
|
"captions": "Chọn ngôn ngữ của phụ đề",
|
||||||
|
"captionPreferences": "Làm cho phụ đề trông như thế nào bạn muốn",
|
||||||
|
"playbackSpeed": "Thay đổi tốc độ phát"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fatalError": "Trình phát video đã gặp phải lỗi nghiêm trọng, vui lòng báo cáo sự cố trên <0>máy chủ Discord</0> hoặc trên <1>GitHub</1>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Cài đặt",
|
||||||
|
"language": "Ngôn ngữ",
|
||||||
|
"captionLanguage": "Ngôn ngữ phụ đề"
|
||||||
|
},
|
||||||
|
"v3": {
|
||||||
|
"newSiteTitle": "Phiên bản mới đã được phát hành!",
|
||||||
|
"newDomain": "https://movie-web.app",
|
||||||
|
"newDomainText": "movie-web sẽ sớm chuyển sang trang mới: <0>https://movie-web.app</0>. Hãy đảm bảo rằng các đánh dấu đã được cập nhật vì <1>trang web cũ sẽ dừng hoạt động vào {{date}}.</1>",
|
||||||
|
"tireless": "Chúng tôi đã làm việc vất vả để tạo phiên bản mới này, chúng tôi hy vọng bạn sẽ thích những gì chúng tôi đã nung nấu trong những tháng qua.",
|
||||||
|
"leaveAnnouncement": "Hãy đưa tôi đến đó!"
|
||||||
|
},
|
||||||
|
"casting": {
|
||||||
|
"casting": "Đang truyền tới thiết bị..."
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"offline": "Hãy kiểm tra kết nối Internet của bạn"
|
||||||
|
}
|
||||||
|
}
|
|
@ -99,10 +99,10 @@ export function EpisodeSelectionPopout() {
|
||||||
<>
|
<>
|
||||||
<FloatingView {...pageProps("seasons")} height={600} width={375}>
|
<FloatingView {...pageProps("seasons")} height={600} width={375}>
|
||||||
<FloatingCardView.Header
|
<FloatingCardView.Header
|
||||||
title={t("videoPlayer.popouts.seasons")}
|
title={t("videoPlayer.popouts.seasons.title")}
|
||||||
description={t("videoPlayer.popouts.descriptions.seasons")}
|
description={t("videoPlayer.popouts.descriptions.seasons")}
|
||||||
goBack={() => navigate("/episodes")}
|
goBack={() => navigate("/episodes")}
|
||||||
backText={`To ${currentSeasonInfo?.title.toLowerCase()}`}
|
backText={currentSeasonInfo?.title}
|
||||||
/>
|
/>
|
||||||
<FloatingCardView.Content>
|
<FloatingCardView.Content>
|
||||||
{currentSeasonInfo
|
{currentSeasonInfo
|
||||||
|
@ -115,12 +115,15 @@ export function EpisodeSelectionPopout() {
|
||||||
{season.title}
|
{season.title}
|
||||||
</PopoutListEntry>
|
</PopoutListEntry>
|
||||||
))
|
))
|
||||||
: "No season"}
|
: t("videoPlayer.popouts.seasons.noSeason")}
|
||||||
</FloatingCardView.Content>
|
</FloatingCardView.Content>
|
||||||
</FloatingView>
|
</FloatingView>
|
||||||
<FloatingView {...pageProps("episodes")} height={600} width={375}>
|
<FloatingView {...pageProps("episodes")} height={600} width={375}>
|
||||||
<FloatingCardView.Header
|
<FloatingCardView.Header
|
||||||
title={currentSeasonInfo?.title ?? "Unknown season"}
|
title={
|
||||||
|
currentSeasonInfo?.title ??
|
||||||
|
t("videoPlayer.popouts.episodes.unknown")
|
||||||
|
}
|
||||||
description={t("videoPlayer.popouts.descriptions.episode")}
|
description={t("videoPlayer.popouts.descriptions.episode")}
|
||||||
goBack={closePopout}
|
goBack={closePopout}
|
||||||
close
|
close
|
||||||
|
@ -130,7 +133,7 @@ export function EpisodeSelectionPopout() {
|
||||||
onClick={() => navigate("/episodes/seasons")}
|
onClick={() => navigate("/episodes/seasons")}
|
||||||
className="flex cursor-pointer items-center space-x-2 transition-colors duration-200 hover:text-white"
|
className="flex cursor-pointer items-center space-x-2 transition-colors duration-200 hover:text-white"
|
||||||
>
|
>
|
||||||
<span>Other seasons</span>
|
<span>{t("videoPlayer.popouts.seasons.other")}</span>
|
||||||
<Icon icon={Icons.CHEVRON_RIGHT} />
|
<Icon icon={Icons.CHEVRON_RIGHT} />
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
@ -181,7 +184,7 @@ export function EpisodeSelectionPopout() {
|
||||||
})}
|
})}
|
||||||
</PopoutListEntry>
|
</PopoutListEntry>
|
||||||
))
|
))
|
||||||
: "No episodes"}
|
: t("videoPlayer.popouts.episodes.noEpisode")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</FloatingCardView.Content>
|
</FloatingCardView.Content>
|
||||||
|
|
Loading…
Reference in a new issue