Merge pull request #598 from movie-web/dev

Release v4.1.3
This commit is contained in:
William Oldham 2023-12-27 23:10:10 +00:00 committed by GitHub
commit 80ad269dcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1543 additions and 421 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "movie-web", "name": "movie-web",
"version": "4.1.2", "version": "4.1.3",
"private": true, "private": true,
"homepage": "https://movie-web.app", "homepage": "https://movie-web.app",
"scripts": { "scripts": {

View File

@ -188,7 +188,6 @@
"disclaimer": "يتم أخذ التنزيلات مباشرةً من قبل مقدم الخدمة. movie-web لاسيطرة له على كيفية توفير تلك التنزيلات.", "disclaimer": "يتم أخذ التنزيلات مباشرةً من قبل مقدم الخدمة. movie-web لاسيطرة له على كيفية توفير تلك التنزيلات.",
"downloadCaption": "تنزيل مقاطع الترجمة الحالية", "downloadCaption": "تنزيل مقاطع الترجمة الحالية",
"downloadVideo": "تنزيل الفيديو", "downloadVideo": "تنزيل الفيديو",
"hlsExplanation": "هذا الوسيط هو بثٌ مباشر من نوع HTTP، لذا لايمكن تنزيله من movie-web.",
"onAndroid": { "onAndroid": {
"1": "للتنزيل على أندرويد، أنقر زر التنزيل وفي الصفحة الموالية <bold>إضغط باستمرار</bold> على الفيديو، وبعدها اختر <bold>حفظ</bold>.", "1": "للتنزيل على أندرويد، أنقر زر التنزيل وفي الصفحة الموالية <bold>إضغط باستمرار</bold> على الفيديو، وبعدها اختر <bold>حفظ</bold>.",
"shortTitle": "تنزيل / Android", "shortTitle": "تنزيل / Android",

View File

@ -189,7 +189,6 @@
"disclaimer": "Stahování probíhá přímo u poskytovatele. movie-web nemá kontrolu nad tím, jak jsou stahování poskytovány.", "disclaimer": "Stahování probíhá přímo u poskytovatele. movie-web nemá kontrolu nad tím, jak jsou stahování poskytovány.",
"downloadCaption": "Stáhnout titulky", "downloadCaption": "Stáhnout titulky",
"downloadVideo": "Stáhnout video", "downloadVideo": "Stáhnout video",
"hlsExplanation": "Toto médium je proud HLS, který nelze stáhnout na movie-web.",
"onAndroid": { "onAndroid": {
"1": "Na Androidu klikněte na tlačítko stahování, poté na nové stránce <bold>klepněte a podržte</bold> na videu a poté vyberte <bold>uložit</bold>.", "1": "Na Androidu klikněte na tlačítko stahování, poté na nové stránce <bold>klepněte a podržte</bold> na videu a poté vyberte <bold>uložit</bold>.",
"shortTitle": "Stahování / Android", "shortTitle": "Stahování / Android",

View File

@ -55,7 +55,7 @@
"text": "Hast du es korrekt konfiguriert?", "text": "Hast du es korrekt konfiguriert?",
"title": "Server nicht erreichbar" "title": "Server nicht erreichbar"
}, },
"host": "Du verbindest dich zu <0>{{hostname}}</0> - stelle sicher, dass du diesem vertraust, bevor du einen Account erstellst", "host": "Du verbindest dich mit <0>{{hostname}}</0> - stelle sicher das du dem Server vertraust bevor du ein Konto erstellst",
"no": "Zurück", "no": "Zurück",
"title": "Vertraust du diesem Server?", "title": "Vertraust du diesem Server?",
"yes": "Ich vertraue diesem Server" "yes": "Ich vertraue diesem Server"
@ -189,7 +189,6 @@
"disclaimer": "Videos werden direkt vom Provider heruntergeladen. movie-web hat nicht steuern, wie die Downloads bereitgestellt werden.", "disclaimer": "Videos werden direkt vom Provider heruntergeladen. movie-web hat nicht steuern, wie die Downloads bereitgestellt werden.",
"downloadCaption": "Ausgewählte Untertitel herunterladen", "downloadCaption": "Ausgewählte Untertitel herunterladen",
"downloadVideo": "Video herunterladen", "downloadVideo": "Video herunterladen",
"hlsExplanation": "Dieses Video ist ein HLS-Stream, welcher auf movie-web nicht heruntergeladen werden kann.",
"onAndroid": { "onAndroid": {
"1": "Um auf Android Herunterzuladen, tippe auf den Download-Button, <bold>tippe und halte</bold> auf der neuen Seite auf das Video und wähle <bold>Speichern</bold> aus.", "1": "Um auf Android Herunterzuladen, tippe auf den Download-Button, <bold>tippe und halte</bold> auf der neuen Seite auf das Video und wähle <bold>Speichern</bold> aus.",
"shortTitle": "Download / Android", "shortTitle": "Download / Android",
@ -238,7 +237,7 @@
"sources": { "sources": {
"failed": { "failed": {
"text": "Beim Versuch, Videos zu finden, ist ein Fehler aufgetreten. Bitte versuche es mit einer anderen Quelle.", "text": "Beim Versuch, Videos zu finden, ist ein Fehler aufgetreten. Bitte versuche es mit einer anderen Quelle.",
"title": "Scrapen fehlgeschlagen" "title": "Fehler beim Laden"
}, },
"noEmbeds": { "noEmbeds": {
"text": "Es konnten keine Embeds gefunden werden. Bitte versuchen es mit einer anderen Quelle.", "text": "Es konnten keine Embeds gefunden werden. Bitte versuchen es mit einer anderen Quelle.",

View File

@ -188,8 +188,9 @@
"downloads": { "downloads": {
"title": "Download", "title": "Download",
"disclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.", "disclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.",
"hlsExplanation": "This media is a HLS stream which cannot be downloaded on movie-web.", "hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided. Please note that you are downloading an HLS playlist, this is intended for users familiar with advanced multimedia streaming.",
"downloadVideo": "Download video", "downloadVideo": "Download video",
"downloadPlaylist": "Download playlist",
"downloadCaption": "Download current caption", "downloadCaption": "Download current caption",
"onPc": { "onPc": {
"1": "On PC, click the download button then, on the new page, right click the video and select <bold>Save video as</bold>", "1": "On PC, click the download button then, on the new page, right click the video and select <bold>Save video as</bold>",

420
src/assets/locales/es.json Normal file
View File

@ -0,0 +1,420 @@
{
"about": {
"description": "movie-web es una aplicación web que busca transmisiones en internet. El equipo tiene como objetivo un enfoque principalmente minimalista para consumir contenido.",
"faqTitle": "Preguntas frecuentes",
"q1": {
"body": "movie-web no aloja ningún contenido. Cuando haces clic en algo para ver, se busca en internet el medio seleccionado (En la pantalla de carga y en la pestaña 'fuentes de vídeo' puedes ver qué fuente estás utilizando). El contenido nunca se carga en movie-web, todo se realiza a través de este mecanismo de búsqueda.",
"title": "¿De dónde proviene el contenido?"
},
"q2": {
"body": "No es posible solicitar una serie o película, movie-web no gestiona ningún contenido. Todo el contenido se ve a través de fuentes en internet.",
"title": "¿Dónde puedo solicitar una serie o película?"
},
"q3": {
"body": "Nuestros resultados de búsqueda están alimentados por The Movie Database (TMDB) y se muestran independientemente de si nuestras fuentes realmente tienen el contenido.",
"title": "Los resultados de búsqueda muestran la serie o película, ¿por qué no puedo reproducirla?"
},
"title": "Acerca de movie-web"
},
"actions": {
"copied": "Copiado",
"copy": "Copiar"
},
"auth": {
"createAccount": "¿Todavía no tienes una cuenta? <0>Crea una cuenta.</0>",
"deviceNameLabel": "Nombre del dispositivo",
"deviceNamePlaceholder": "Teléfono personal",
"generate": {
"description": "Tu frase de contraseña actúa como tu nombre de usuario y contraseña. Asegúrate de mantenerlas seguras, ya que las necesitarás para iniciar sesión en tu cuenta",
"next": "He guardado mi frase de contraseña",
"passphraseFrameLabel": "Frase de contraseña",
"title": "Tu frase de contraseña"
},
"hasAccount": "¿Ya tienes una cuenta? <0>Inicia sesión aquí.</0>",
"login": {
"description": "Por favor, ingresa tu frase de contraseña para iniciar sesión en tu cuenta",
"deviceLengthError": "Por favor, ingresa un nombre de dispositivo",
"passphraseLabel": "Frase de contraseña de 12 palabras",
"passphrasePlaceholder": "Frase de contraseña",
"submit": "Iniciar sesión",
"title": "Inicia sesión en tu cuenta",
"validationError": "Contraseña incorrecta o incompleta"
},
"register": {
"information": {
"color1": "Color de perfil uno",
"color2": "Color de perfil dos",
"header": "Ingresa un nombre para tu dispositivo, elige colores, y un ícono de usuario de tu elección",
"icon": "Ícono de usuario",
"next": "Siguiente",
"title": "Información de la cuenta"
}
},
"trust": {
"failed": {
"text": "¿Lo configuraste correctamente?",
"title": "No se pudo conectar al servidor"
},
"host": "Te estás conectando a <0>{{hostname}}</0> - por favor, confirma si confías en este antes de crear una cuenta",
"no": "Regresar",
"title": "¿Confías en este servidor?",
"yes": "Confío en este servidor"
},
"verify": {
"description": "Por favor, ingresa tu frase de contraseña anterior para confirmar que la has guardado y para crear tu cuenta",
"invalidData": "Los datos no son válidos",
"noMatch": "La frase de contraseña no coincide",
"passphraseLabel": "Tu frase de contraseña de 12 palabras",
"recaptchaFailed": "La validación de ReCaptcha falló",
"register": "Crear cuenta",
"title": "Confirma tu frase de contraseña"
}
},
"errors": {
"badge": "Se descompuso",
"details": "Detalles del error",
"reloadPage": "Recargar la página",
"showError": "Mostrar detalles del error",
"title": "¡Encontramos un error!"
},
"footer": {
"legal": {
"disclaimer": "Descargo de responsabilidad",
"disclaimerText": "movie-web no aloja ningún archivo, simplemente enlaza a servicios de terceros. Los problemas legales deben ser tratados con los proveedores de archivos y servicios. movie-web no se hace responsable de los archivos multimedia mostrados por los proveedores de vídeo."
},
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "GitHub"
},
"tagline": "Ve tus series y películas favoritas con esta aplicación de transmisión de código abierto."
},
"global": {
"name": "movie-web",
"pages": {
"about": "Acerca de",
"dmca": "DMCA",
"login": "Iniciar sesión",
"pagetitle": "{{title}} - movie-web",
"register": "Registrarse",
"settings": "Configuración"
}
},
"home": {
"bookmarks": {
"sectionTitle": "Marcadores"
},
"continueWatching": {
"sectionTitle": "Continuar viendo"
},
"mediaList": {
"stopEditing": "Detener edición"
},
"search": {
"allResults": "¡Eso es todo lo que tenemos!",
"failed": "¡Error al encontrar contenido, inténtalo de nuevo!",
"loading": "Cargando...",
"noResults": "¡No pudimos encontrar nada!",
"placeholder": "¿Qué te gustaría ver?",
"sectionTitle": "Resultados de búsqueda"
},
"titles": {
"day": {
"default": "¿Qué te gustaría ver esta tarde?"
},
"morning": {
"default": "¿Qué te gustaría ver esta mañana?",
"extra": [
"Escuché que “Antes del amanecer” es buena"
]
},
"night": {
"default": "¿Qué te gustaría ver esta noche?",
"extra": [
"¿Cansado? Escuché que “El Exorcista” es buena."
]
}
}
},
"media": {
"episodeDisplay": "T{{season}} E{{episode}}",
"types": {
"movie": "Película",
"show": "Serie"
}
},
"navigation": {
"banner": {
"offline": "Verifica tu conexión a internet"
},
"menu": {
"about": "Acerca de nosotros",
"donation": "Donar",
"logout": "Cerrar sesión",
"register": "Sincronizar con la nube",
"settings": "Configuración",
"support": "Soporte"
}
},
"notFound": {
"badge": "No encontrado",
"goHome": "Volver a inicio",
"message": "Buscamos en todas partes: debajo de los contenedores, en el armario, detrás del proxy, pero al final no pudimos encontrar la página que estás buscando.",
"title": "No se puede encontrar esa página"
},
"overlays": {
"close": "Cerrar"
},
"player": {
"back": {
"default": "Volver al inicio",
"short": "Volver"
},
"casting": {
"enabled": "Transmitiendo a dispositivo..."
},
"menus": {
"captions": {
"customChoice": "Seleccionar subtítulo desde un archivo",
"customizeLabel": "Personalizar",
"offChoice": "Apagado",
"settings": {
"delay": "Retraso de subtítulos",
"fixCapitals": "Corregir mayúsculas"
},
"title": "Subtítulos",
"unknownLanguage": "Desconocido"
},
"downloads": {
"disclaimer": "Las descargas se realizan directamente desde el proveedor. movie-web no tiene control sobre cómo se proporcionan las descargas.",
"downloadCaption": "Descargar subtítulo actual",
"downloadVideo": "Descargar vídeo",
"onAndroid": {
"1": "Para descargar en Android, haz clic en el botón de descarga y luego, en la nueva página, <bold>mantén presionado</bold> el vídeo y selecciona <bold>guardar</bold>.",
"shortTitle": "Descargar / Android",
"title": "Descargando en Android"
},
"onIos": {
"1": "Para descargar en iOS, haz clic en el botón de descarga y luego, en la nueva página, haz clic en <bold><ios_share /></bold>, luego <bold>Guardar en archivos <ios_files /></bold>.",
"shortTitle": "Descargar / iOS",
"title": "Descargando en iOS"
},
"onPc": {
"1": "En una PC, haz clic en el botón de descarga y luego, en la nueva página, haz clic derecho en el vídeo y selecciona <bold>Guardar vídeo como...</bold>",
"shortTitle": "Descargar / PC",
"title": "Descargando en PC"
},
"title": "Descargar"
},
"episodes": {
"button": "Episodios",
"emptyState": "No hay episodios en esta temporada, ¡Intenta más tarde!",
"episodeBadge": "E{{episode}}",
"loadingError": "Error al cargar la temporada",
"loadingList": "Cargando...",
"loadingTitle": "Cargando..."
},
"playback": {
"speedLabel": "Velocidad de reproducción",
"title": "Configuración de reproducción"
},
"quality": {
"automaticLabel": "Calidad automática",
"hint": "Puedes intentar <0>cambiar de fuente</0> para obtener diferentes opciones de calidad.",
"iosNoQuality": "Debido a limitaciones definidas por Apple, la selección de calidad no está disponible en iOS para esta fuente. Puedes intentar <0>cambiar a otra fuente</0> para obtener diferentes opciones de calidad.",
"title": "Calidad"
},
"settings": {
"captionItem": "Configuración de subtítulos",
"downloadItem": "Descargar",
"enableCaptions": "Habilitar subtítulos",
"experienceSection": "Experiencia de visualización",
"playbackItem": "Configuración de reproducción",
"qualityItem": "Calidad",
"sourceItem": "Fuentes de vídeo",
"videoSection": "Configuración de vídeo"
},
"sources": {
"failed": {
"text": "Se produjo un error al intentar encontrar vídeos, por favor intenta con una fuente diferente.",
"title": "Error al obtener"
},
"noEmbeds": {
"text": "No pudimos encontrar ninguna embed, por favor intenta con una fuente diferente.",
"title": "No se encontraron embeds"
},
"noStream": {
"text": "Esta fuente no tiene transmisiones para esta película o serie.",
"title": "Sin transmisión"
},
"title": "Fuentes",
"unknownOption": "Desconocida"
}
},
"metadata": {
"failed": {
"badge": "Error",
"homeButton": "Ir al inicio",
"text": "No se pudieron cargar los metadatos del contenido de TMDB. Por favor, verifica si TMDB está caído o bloqueado en tu conexión a internet.",
"title": "Error al cargar los metadatos"
},
"notFound": {
"badge": "No encontrado",
"homeButton": "Volver al inicio",
"text": "No pudimos encontrar el contenido que solicitaste. Ya sea que se haya eliminado o se haya modificado la URL.",
"title": "No se pudo encontrar ese contenido."
}
},
"nextEpisode": {
"cancel": "Cancelar",
"next": "Siguiente episodio"
},
"playbackError": {
"badge": "Error de reproducción",
"errors": {
"errorAborted": "La obtención del contenido fue cancelada por solicitud del usuario.",
"errorDecode": "A pesar de haber sido determinado previamente como utilizable, se produjo un error al intentar decodificar el recurso del contenido, lo que resultó en un error.",
"errorGenericMedia": "Se produjo un error desconocido en el contenido.",
"errorNetwork": "Se produjo un error de red que impidió obtener el contenido de manera exitosa, a pesar de haber estado disponible anteriormente.",
"errorNotSupported": "El contenido o el proveedor del contenido no es compatible."
},
"homeButton": "Ir al inicio",
"text": "Se produjo un error al intentar reproducir el contenido. Por favor, inténtalo de nuevo.",
"title": "¡No se pudo reproducir el vídeo!"
},
"scraping": {
"items": {
"failure": "Ocurrió un error",
"notFound": "No tiene el vídeo",
"pending": "Verificando vídeos..."
},
"notFound": {
"badge": "No encontrado",
"detailsButton": "Mostrar detalles",
"homeButton": "Ir al inicio",
"text": "Hemos buscado en nuestros proveedores y no podemos encontrar el contenido que estás buscando. No alojamos el contenido y no tenemos control sobre lo que está disponible. Haz clic en 'Mostrar detalles' a continuación para obtener más información.",
"title": "No pudimos encontrar eso"
}
},
"time": {
"regular": "{{timeWatched}} / {{duration}}",
"remaining": "{{timeLeft}} restante • Finaliza a las {{timeFinished, datetime}}",
"shortRegular": "{{timeWatched}}",
"shortRemaining": "-{{timeLeft}}"
}
},
"screens": {
"dmca": {
"text": "¡Bienvenido a la página de contacto DMCA de movie-web! Respetamos los derechos de propiedad intelectual y queremos abordar cualquier problema de derechos de autor de manera rápida. Si cree que su trabajo con derechos de autor se ha utilizado incorrectamente en nuestra plataforma, envíe un aviso DMCA detallado al correo electrónico que se muestra a continuación. Incluya una descripción del material con derechos de autor, sus datos de contacto y una declaración de buena fe. Estamos comprometidos a resolver estos asuntos de manera pronta y agradecemos su cooperación para mantener a movie-web como un lugar que respeta la creatividad y los derechos de autor.",
"title": "DMCA"
},
"loadingApp": "Cargando la aplicación",
"loadingUser": "Cargando tu perfil",
"loadingUserError": {
"logout": "Cerrar sesión",
"reset": "Restablecer servidor personalizado",
"text": "Error al cargar tu perfil",
"textWithReset": "Error al cargar tu perfil desde tu servidor personalizado, ¿Quieres restablecerlo al servidor predeterminado?"
},
"migration": {
"failed": "Error al migrar tus datos.",
"inProgress": "Por favor espera, estamos migrando tus datos. Esto no debería tomar mucho tiempo."
}
},
"settings": {
"account": {
"accountDetails": {
"deviceNameLabel": "Nombre del dispositivo",
"deviceNamePlaceholder": "Teléfono personal",
"editProfile": "Editar",
"logoutButton": "Cerrar sesión"
},
"actions": {
"delete": {
"button": "Eliminar cuenta",
"confirmButton": "Eliminar cuenta",
"confirmDescription": "¿Estás seguro de que quieres eliminar tu cuenta? ¡Todos tus datos se perderán!",
"confirmTitle": "¿Estás seguro?",
"text": "Esta acción es irreversible. Todos los datos se eliminarán y no se podrán recuperar.",
"title": "Eliminar cuenta"
},
"title": "Acciones"
},
"devices": {
"deviceNameLabel": "Nombre del dispositivo",
"failed": "Error al cargar las sesiones",
"removeDevice": "Eliminar",
"title": "Dispositivos"
},
"profile": {
"finish": "Finalizar edición",
"firstColor": "Color de perfil uno",
"secondColor": "Color de perfil dos",
"title": "Editar imagen de perfil",
"userIcon": "Icono de usuario"
},
"register": {
"cta": "Empezar",
"text": "Comparte tu progreso de visualización entre dispositivos y manténlos sincronizados.",
"title": "Sincronizar con la nube"
},
"title": "Cuenta"
},
"appearance": {
"activeTheme": "Activo",
"themes": {
"blue": "Azul",
"default": "Predeterminado",
"gray": "Gris",
"red": "Rojo",
"teal": "Turquesa"
},
"title": "Apariencia"
},
"captions": {
"backgroundLabel": "Opacidad del fondo",
"colorLabel": "Color",
"previewQuote": "No debo temer. El miedo es el asesino de la mente.",
"textSizeLabel": "Tamaño del texto",
"title": "Subtítulos"
},
"connections": {
"server": {
"description": "Si deseas conectarte a un backend personalizado para almacenar tus datos, habilita esto y proporciona la URL.",
"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.",
"emptyState": "Aún no hay workers, agrega uno a continuación",
"label": "Usar proxy workers personalizados",
"urlLabel": "URL de los workers",
"urlPlaceholder": "https://"
}
},
"locale": {
"language": "Idioma de la aplicación",
"languageDescription": "Idioma aplicado a toda la aplicación.",
"title": "Idioma"
},
"reset": "Restablecer",
"save": "Guardar",
"sidebar": {
"info": {
"appVersion": "Versión de la aplicación",
"backendUrl": "URL del backend",
"backendVersion": "Versión del backend",
"hostname": "Nombre de host",
"insecure": "No seguro",
"notLoggedIn": "No has iniciado sesión",
"secure": "Seguro",
"title": "Información de la aplicación",
"unknownVersion": "Desconocida",
"userId": "ID de usuario"
}
},
"unsaved": "Tienes cambios sin guardar"
}
}

281
src/assets/locales/et.json Normal file
View File

@ -0,0 +1,281 @@
{
"about": {
"description": "movie-web on veebirakendus, mis otsib internetti voogude jaoks. Meeskonna eesmärk on enamasti minimalistlik lähenemine sisu tarbimisele.",
"q1": {
"body": "movie-web ei hoiusta enda sisu. Kui klõpsate, et midagi vaadata, otsitakse valitud meediat internetist (laadimisekraanil ja vahekaardil \"videoallikad\" näete, millist allikat te kasutate). Meediat ei lae movie-web kunagi üles, kõik toimub selle otsingumehhanismi kaudu."
},
"q2": {
"body": "Saadet või filmi ei ole võimalik taotelda, movie-web ei halda mingit sisu. Kogu sisu vaadatakse interneti allikate kaudu."
}
},
"auth": {
"createAccount": "Ei ole kontot veel?<0>Loo konto.</0>",
"deviceNameLabel": "Seadme nimi",
"deviceNamePlaceholder": "Isiklik telefon",
"generate": {
"description": "Teie parool toimib teie kasutajanime ja paroolina. Veenduge, et see oleks ohutus kohas, kuna peate kasutama seda, et logida oma kontosse sisse",
"next": "Olen salvestanud oma parooli",
"passphraseFrameLabel": "Parool",
"title": "Sinu parool"
},
"hasAccount": "On juba konto? <0>Logi sisse siin.</0>",
"login": {
"description": "Palun sisestage parool, et logida kontosse sisse",
"deviceLengthError": "Palun sisesta seadme nimi",
"passphraseLabel": "12-Sõnaline parool",
"passphrasePlaceholder": "Parool",
"submit": "Logi sisse",
"title": "Logi sisse oma kontosse",
"validationError": "Vale vōi mittetäielik parool"
},
"register": {
"information": {
"color1": "Profiili värv üks",
"color2": "Profiili värv kaks",
"header": "Sisestage oma seadme nimi ja valige värvid ning kasutajaikoon",
"icon": "Kasutaja ikoon",
"next": "Järgmine",
"title": "Kontoteave"
}
},
"trust": {
"failed": {
"text": "Kas sa seadistasid selle õigesti?",
"title": "Serveriga ühenduse loomine ebaõnnestus"
},
"host": "Ühendate <0>{{hostname}}</0> - enne konto tegemist kinnitage, et usaldate seda",
"no": "Tagasi",
"title": "Kas usaldate seda serverit?",
"yes": "Usaldan seda serverit"
},
"verify": {
"description": "Palun sisestage oma salasõna, et kinnitada, et olete selle salvestanud ja luua oma konto",
"invalidData": "Andmed ei kehti",
"noMatch": "Parool ei klapi",
"passphraseLabel": "Sinu 12-sõnaline parool",
"recaptchaFailed": "ReCaptcha valideerimine ebaõnnestua",
"register": "Loo konto",
"title": "Kinnita oma parool"
}
},
"errors": {
"badge": "Läks katki",
"details": "Vea üksikasjad",
"reloadPage": "Värskenda leht",
"showError": "Näita vea üksikasju",
"title": "Tekkis viga!"
},
"footer": {
"legal": {
"disclaimerText": "movie-web ei hoiusta ühtegi faili, vaid ainult lingib kolmandate osapoolte teenustele. Juriidilised küsimused tuleks lahendada failihostide ja teenusepakkujatega. movie-web ei vastuta videopakkujate poolt näidatud meediafailide eest."
}
},
"global": {
"name": "movie-web",
"pages": {
"about": "Meist",
"dmca": "DMCA",
"login": "Logi sisse",
"pagetitle": "{{title}} - movie-web",
"register": "Registreeri",
"settings": "Sätted"
}
},
"home": {
"bookmarks": {
"sectionTitle": "Järjehoidjad"
},
"continueWatching": {
"sectionTitle": "Jätka vaatamist"
},
"mediaList": {
"stopEditing": "Lõpeta redigeerimine"
},
"search": {
"allResults": "See on kõik, mis meil on!",
"failed": "Meedia leidmine ebaõnnestus, proovige uuesti!",
"loading": "Laadimine....",
"noResults": "Me ei leidnud midagi!",
"placeholder": "Mida tahate vaadata?",
"sectionTitle": "Otsingutulemused"
},
"titles": {
"day": {
"default": "Mida te soovite täna pärastlõunal vaadata?"
},
"morning": {
"default": "Mida te soovite täna hommikul vaadata?",
"extra": [
"Ma kuulsin, et Before Sunrise on hea"
]
},
"night": {
"default": "Mida te soovite täna õhtul vaadata?",
"extra": [
"Väsinud? Olen kuulnud, et The Exorcist on hea."
]
}
}
},
"media": {
"episodeDisplay": "S{{season}} E{{episode}}",
"types": {
"movie": "Film",
"show": "Saade"
}
},
"notFound": {
"badge": "Ei leitud",
"goHome": "Tagasi koju",
"message": "Otsisime kõikjalt: prügikastide alt, kapist, proksi tagant, kuid lõpuks ei leidnud otsitud lehte.",
"title": "Ei leidnud seda lehekülge"
},
"overlays": {
"close": "Sulge"
},
"player": {
"back": {
"default": "Tagasi koju",
"short": "Tagasi"
},
"menus": {
"captions": {
"customChoice": "Vali subtiitrid failist",
"customizeLabel": "Kohanda",
"offChoice": "Välja",
"settings": {
"delay": "Subtiitri viivitus",
"fixCapitals": "Paranda kapitaliseerimine"
},
"title": "Subtiitrid",
"unknownLanguage": "Teadmata"
},
"downloads": {
"disclaimer": "Allalaadimine toimub otse teenusepakkujalt. movie-web ei saa kontrollida, kuidas allalaadimine toimub.",
"downloadCaption": "Lae alla praegused subtiitrid",
"downloadVideo": "Lae alla video",
"onAndroid": {
"1": "Et allalaadida Androidi telefonil, vajuta allalaadimise nupule, siis uuel leheküljel <bold>vajuta ja hoia</bold> video peal, siis vali <bold>salvesta</bold>.",
"shortTitle": "Allalaadimine / Android",
"title": "Androidil allalaadimine"
},
"onIos": {
"1": "Et allalaadida iOS telefonil, vajuta allalaadimise nupule, siis uuel leheküljel vajuta <bold><ios_share /></bold>, siis <bold>Salvesta failidesse <ios_files /></bold>",
"shortTitle": "Allalaadimine / iOS",
"title": "iOSil allalaadimine"
},
"onPc": {
"1": "Klõpsake arvutis allalaadimise nupule, seejärel klõpsake uuel lehel parema klõpsuga videol ja valige <bold>Salvesta video</bold>",
"shortTitle": "Allalaadimine / Arvutis",
"title": "Arvutis allalaadimine"
},
"title": "Lae alla"
},
"episodes": {
"button": "Episoodid",
"emptyState": "Selles hooajas puuduvad episoodid, vaadake hiljem uuesti!",
"episodeBadge": "E{{episode}}",
"loadingError": "Hooaja laadimine ebaōnnestus",
"loadingList": "Laadimine...",
"loadingTitle": "Laadimine..."
},
"playback": {
"speedLabel": "Taasesituse kiirus",
"title": "Taasesituse sätted"
},
"quality": {
"automaticLabel": "Automaatne kvaliteet",
"hint": "Võid proovida <0>vahetada allikat</0>, et saada teisi kvaliteedi valikuid.",
"iosNoQuality": "Apple'i poolt määratletud piirangute tõttu ei ole sellel allikal kvaliteedivalik saadaval. Te võite proovida <0>vahetada teisele allikale</0>, et saada erinevaid kvaliteedivalikuid.",
"title": "Kvaliteet"
},
"settings": {
"captionItem": "Subtiitrite sätted",
"downloadItem": "Lae alla",
"enableCaptions": "Luba subtiitrid",
"experienceSection": "Vaatamise kogemus",
"playbackItem": "Taasesituse sätted",
"qualityItem": "Kvaliteet",
"sourceItem": "Video allikad",
"videoSection": "Video sätted"
},
"sources": {
"failed": {
"text": "Videote leidmisel tekkis viga, palun proovige mõnda muud allikat.",
"title": "Ei õnnestunud kraapida"
},
"noEmbeds": {
"text": "Me ei leidnud ühtegi manust, proovige twist allikat.",
"title": "Ei leitud manuseid"
},
"noStream": {
"text": "Sellel allikal ei ole selle filmi või seriaali jaoks ühtegi voogedastust.",
"title": "Puudub voog"
},
"title": "Allikad",
"unknownOption": "Teadmata"
}
},
"metadata": {
"failed": {
"badge": "Ebaōnnestus",
"homeButton": "Mine koju",
"text": "Meedia metaandmeid ei õnnestunud TMDB-st laadida. Palun kontrollige, kas TMDB on maas või see on teie internetiühenduses blokeeritud.",
"title": "Metaandmete laadimine ebaõnnestus"
},
"notFound": {
"badge": "Ei leitud",
"homeButton": "Tagasi koju",
"text": "Me ei leidnud teie soovitud meediat. Kas see on eemaldatud või olete URL-i muutnud.",
"title": "Ei leidnud seda meediat."
}
},
"nextEpisode": {
"cancel": "Tühista",
"next": "Järgmine episood"
},
"playbackError": {
"badge": "Taasesituse viga",
"errors": {
"errorAborted": "Meedia kättesaamine katkestati kasutaja taotlusel.",
"errorDecode": "Vaatamata sellele, et eelnevalt oli kindlaks tehtud, et see on kasutatav, tekkis viga meediaressursi dekodeerimisel, mille tulemuseks oli viga.",
"errorGenericMedia": "Tekkis tundmatu meediaviga.",
"errorNetwork": "Tekkis võrguviga, mis takistas meedia edukat kättesaamist, kuigi see oli varem saadaval.",
"errorNotSupported": "Meedia või meediapakkuja objekt ei ole toetatud."
},
"homeButton": "Mine koju",
"text": "Tekkis viga meedia mängimisel. Palun proovige uuesti.",
"title": "Video mängimine ebaōnnestus!"
},
"scraping": {
"items": {
"failure": "Tekkis viga",
"notFound": "Ei ole videot",
"pending": "Otsin videoid..."
},
"notFound": {
"badge": "Ei leitud",
"detailsButton": "Näita üksikasju",
"homeButton": "Mine koju",
"text": "Me otsisime läbi meie teenusepakkujad ja ei leidnud teie poolt otsitud meediat! Me ei halda meediat ja meil ei ole kontrolli selle üle, mis on saadaval. Täpsema teabe saamiseks klõpsake allpool nupule \"Näita üksikasju\".",
"title": "Me ei leidnud seda"
}
},
"time": {
"regular": "{{timeWatched}} / {{duration}}",
"remaining": "{{timeLeft}} alles • Lõppeb {{timeFinished, datetime}}",
"shortRegular": "{{timeWatched}}",
"shortRemaining": "-{{timeLeft}}"
}
},
"screens": {
"dmca": {
"text": "Tere tulemast movie-webi DMCA kontaktilehele! Me austame intellektuaalomandi õigusi ja soovime kiiresti lahendada kõik autoriõigusega seotud probleemid. Kui usute, et teie autoriõigusega kaitstud tööd on meie platvormil vääralt kasutatud, saatke palun üksikasjalik DMCA-teade alljärgnevale e-posti aadressile. Palun lisage autoriõigusega kaitstud materjali kirjeldus, oma kontaktandmed ja avaldus heauskse veendumuse kohta. Oleme pühendunud nende küsimuste kiirele lahendamisele ja hindame teie koostööd, et movie-web oleks koht, kus austatakse loovust ja autoriõigusi."
},
"loadingApp": "Rakenduse laadimine",
"loadingUser": "Teie profiili laadimine",
"loadingUserError": {
"text": "Profiili laadimine ebaōnnestus"
}
}
}

View File

@ -189,7 +189,6 @@
"disclaimer": "Les téléchargements sont effectués directement par le fournisseur. movie-web n'a aucun contrôle sur la manière dont les téléchargements sont effectués.", "disclaimer": "Les téléchargements sont effectués directement par le fournisseur. movie-web n'a aucun contrôle sur la manière dont les téléchargements sont effectués.",
"downloadCaption": "Télécharger les sous-titres actuels", "downloadCaption": "Télécharger les sous-titres actuels",
"downloadVideo": "Télécharger la vidéo", "downloadVideo": "Télécharger la vidéo",
"hlsExplanation": "Ce média est un flux HLS qui ne peut pas être téléchargé sur movie-web.",
"onAndroid": { "onAndroid": {
"1": "Pour télécharger sur Android, cliquez sur le bouton de téléchargement puis, sur la nouvelle page, <bold>tapez et maintenez </bold> sur la vidéo, puis sélectionnez <bold>enregistrer</bold>.", "1": "Pour télécharger sur Android, cliquez sur le bouton de téléchargement puis, sur la nouvelle page, <bold>tapez et maintenez </bold> sur la vidéo, puis sélectionnez <bold>enregistrer</bold>.",
"shortTitle": "Télécharger / Android", "shortTitle": "Télécharger / Android",

View File

@ -189,7 +189,6 @@
"disclaimer": "ההורדות נלקחות ישירות מהספק. ל-movie-web אין שליטה על האופן שבו מסופקות ההורדות.", "disclaimer": "ההורדות נלקחות ישירות מהספק. ל-movie-web אין שליטה על האופן שבו מסופקות ההורדות.",
"downloadCaption": "הורד את הכתוביות הנוכחיות", "downloadCaption": "הורד את הכתוביות הנוכחיות",
"downloadVideo": "הורד וידאו", "downloadVideo": "הורד וידאו",
"hlsExplanation": "מדיה זו היא זרם HLS שאינו ניתן להורדה ב-movie-web.",
"onAndroid": { "onAndroid": {
"1": "כדי להוריד באנדרואיד, לחץ על כפתור ההורדה ולאחר מכן, בדף החדש, <bold>הקש והחזק</bold> על הסרטון, ולאחר מכן בחר <bold>שמור</bold>.", "1": "כדי להוריד באנדרואיד, לחץ על כפתור ההורדה ולאחר מכן, בדף החדש, <bold>הקש והחזק</bold> על הסרטון, ולאחר מכן בחר <bold>שמור</bold>.",
"shortTitle": "הורדה / אנדרויד", "shortTitle": "הורדה / אנדרויד",

View File

@ -188,7 +188,6 @@
"disclaimer": "Lejupielādes tiek ņemtas tieši no pakalpojumu sniedzēja. Movie-web nevar kontrolēt, kā tiek nodrošinātas lejupielādes.", "disclaimer": "Lejupielādes tiek ņemtas tieši no pakalpojumu sniedzēja. Movie-web nevar kontrolēt, kā tiek nodrošinātas lejupielādes.",
"downloadCaption": "Lejupielādēt pašreizējo parakstu", "downloadCaption": "Lejupielādēt pašreizējo parakstu",
"downloadVideo": "Lejupielādēt video", "downloadVideo": "Lejupielādēt video",
"hlsExplanation": "Šī multivide ir HLS straume, kuru nevar lejupielādēt filmu tīmeklī.",
"onAndroid": { "onAndroid": {
"1": "Lai lejupielādētu operētājsistēmā Android, noklikšķiniet uz lejupielādes pogas, pēc tam jaunajā lapā <bold>pieskarieties videoklipam un turiet to</bold>, pēc tam atlasiet <bold>saglabāt</bold>.", "1": "Lai lejupielādētu operētājsistēmā Android, noklikšķiniet uz lejupielādes pogas, pēc tam jaunajā lapā <bold>pieskarieties videoklipam un turiet to</bold>, pēc tam atlasiet <bold>saglabāt</bold>.",
"shortTitle": "Lejupielādēt / Android", "shortTitle": "Lejupielādēt / Android",

View File

@ -1,271 +1,145 @@
{ {
"about": {
"description": "Minion-web is a banana application that searches the banana for bananas. The banana aims for a mostly banana approach to consuming banana.",
"faqTitle": "Banana questions",
"q1": {
"body": "Minion-web does not banana any banana. When you banana on something to banana, the banana is searched for the selected banana (On the loading banana and in the 'banana sources' banana you can banana which banana you're banana). Banana never gets banana by Minion-web, everything is banana this banana mechanism.",
"title": "Where does the banana come from?"
},
"q2": {
"body": "It's not banana to banana a banana or banana, Minion-web does not banana any banana. All banana is banana through bananas on the banana.",
"title": "Banana can I banana a banana or banana?"
},
"q3": {
"body": "Our banana results are banana by The Banana Banana (TBMB) and banana regardless of whether our bananas actually have the banana.",
"title": "The banana results banana the banana or banana, banana can't I banana it?"
},
"title": "About Minion-web"
},
"actions": {
"copied": "Banana",
"copy": "Banana"
},
"auth": { "auth": {
"createAccount": "Whaaaat? Don't have an account yet? <0>Create an account.</0>",
"deviceNameLabel": "Device name", "deviceNameLabel": "Device name",
"deviceNamePlaceholder": "Banana phone", "deviceNamePlaceholder": "Banana phone",
"generate": {
"description": "Your banana passphrase acts as your banana username and banana password. Make sure to keep it safe as you will need to enter it to banana to your account",
"next": "I have saved my banana passphrase",
"title": "Your banana passphrase"
},
"hasAccount": "Bello! Already have an account? <0>Login here.</0>", "hasAccount": "Bello! Already have an account? <0>Login here.</0>",
"createAccount": "Whaaaat? Don't have an account yet? <0>Create an account.</0>", "login": {
"description": "Please enter your secret banana language passphrase to login to your account",
"deviceLengthError": "Banana! Please enter a device name",
"passphraseLabel": "12-Banana passphrase",
"passphrasePlaceholder": "Banana Passphrase",
"submit": "Bello! Login",
"title": "Login to your account",
"validationError": "Banana language not fluent or incomplete"
},
"register": { "register": {
"information": { "information": {
"title": "Account information",
"color1": "Profile color one", "color1": "Profile color one",
"color2": "Profile color two", "color2": "Profile color two",
"icon": "Minion icon",
"header": "Whaaat? Enter a name for your device and pick colors and a minion icon of your choosing", "header": "Whaaat? Enter a name for your device and pick colors and a minion icon of your choosing",
"next": "Banana!" "icon": "Minion icon",
"next": "Banana!",
"title": "Account information"
} }
}, },
"login": {
"title": "Login to your account",
"description": "Please enter your secret banana language passphrase to login to your account",
"validationError": "Banana language not fluent or incomplete",
"deviceLengthError": "Banana! Please enter a device name",
"submit": "Bello! Login",
"passphraseLabel": "12-Banana passphrase",
"passphrasePlaceholder": "Banana Passphrase"
},
"generate": {
"title": "Your banana passphrase",
"next": "I have saved my banana passphrase",
"description": "Your banana passphrase acts as your banana username and banana password. Make sure to keep it safe as you will need to enter it to banana to your account"
},
"trust": { "trust": {
"title": "Do you trust this server?",
"host": "You are connecting to <0>{{hostname}}</0> - please confirm you trust it before making a banana account",
"failed": { "failed": {
"title": "Failed to reach server", "text": "Did you configure it correctly?",
"text": "Did you configure it correctly?" "title": "Failed to reach server"
}, },
"yes": "I trust this server, banana!", "host": "You are connecting to <0>{{hostname}}</0> - please confirm you trust it before making a banana account",
"no": "Go back, banana" "no": "Go back, banana",
"title": "Do you trust this server?",
"yes": "I trust this server, banana!"
}, },
"verify": { "verify": {
"title": "Confirm your banana passphrase",
"description": "Please enter your banana passphrase from earlier to confirm you have saved it and to create your banana account", "description": "Please enter your banana passphrase from earlier to confirm you have saved it and to create your banana account",
"invalidData": "Banana data is not valid", "invalidData": "Banana data is not valid",
"noMatch": "Banana! Passphrase doesn't match", "noMatch": "Banana! Passphrase doesn't match",
"recaptchaFailed": "Banana! ReCaptcha validation failed",
"passphraseLabel": "Your 12-banana passphrase", "passphraseLabel": "Your 12-banana passphrase",
"register": "Create banana account" "recaptchaFailed": "Banana! ReCaptcha validation failed",
"register": "Create banana account",
"title": "Confirm your banana passphrase"
} }
}, },
"errors": { "errors": {
"badge": "It broke",
"details": "Error banana details", "details": "Error banana details",
"reloadPage": "Reload the banana", "reloadPage": "Reload the banana",
"showError": "Show banana details", "showError": "Show banana details",
"badge": "It broke",
"title": "We encountered a banana!" "title": "We encountered a banana!"
}, },
"notFound": { "footer": {
"badge": "Not found", "legal": {
"title": "Couldn't find that banana", "disclaimer": "Banana",
"message": "We looked everywhere: under the banana, in the banana, behind the banana but ultimately couldn't find the banana you are looking for.", "disclaimerText": "Minion-web does not banana any bananas, it merely banana to 3rd banana bananas. Banana issues should be banana up with the banana bananas and bananas. Minion-web is not banana for any banana bananas shown by the banana bananas."
"goHome": "Back to banana" },
"links": {
"discord": "Banana",
"dmca": "Banana",
"github": "Banana"
},
"tagline": "Banana your favourite bananas and bananas with this open source banana app."
}, },
"global": { "global": {
"name": "banana-web", "name": "banana-web",
"pages": { "pages": {
"pagetitle": "{{title}} - banana-web",
"dmca": "DMCA",
"settings": "Banana Settings",
"about": "About banana", "about": "About banana",
"dmca": "DMCA",
"login": "Banana Login", "login": "Banana Login",
"register": "Banana Register" "pagetitle": "{{title}} - banana-web",
} "register": "Banana Register",
}, "settings": "Banana Settings"
"media": {
"types": {
"movie": "Banana Movie",
"show": "Banana Show"
},
"episodeDisplay": "S{{season}} E{{episode}}"
},
"player": {
"scraping": {
"notFound": {
"badge": "Not found",
"title": "We couldn't find that banana",
"text": "We have searched through our banana providers and cannot find the banana you are looking for! We do not host the banana and have no control over what is available. Please click 'Show details' below for more details.",
"homeButton": "Go home",
"detailsButton": "Show details"
},
"items": {
"pending": "Checking for banana videos...",
"notFound": "Doesn't have the banana video",
"failure": "Error banana occurred"
}
},
"casting": {
"enabled": "Casting to banana..."
},
"playbackError": {
"badge": "Banana Playback error",
"title": "Failed to play banana video!",
"text": "There was an error trying to play the banana. Please try again.",
"homeButton": "Go home",
"errors": {
"errorAborted": "The fetching of the banana was aborted by the user's banana.",
"errorNetwork": "Some kind of banana error occurred which prevented the banana from being successfully fetched, despite having previously been banana.",
"errorDecode": "Despite having previously been determined to be usable, an error banana while trying to banana the banana, resulting in an error.",
"errorNotSupported": "The banana or banana provider object is not banana.",
"errorGenericMedia": "Unknown banana error occurred."
}
},
"metadata": {
"notFound": {
"badge": "Banana Not found",
"title": "Couldn't find that banana.",
"text": "We couldn't find the banana you requested. Either it's been banana or you tampered with the banana.",
"homeButton": "Back to banana"
},
"failed": {
"badge": "Banana Failed",
"title": "Failed to load banana metadata",
"text": "Could not banana the banana's banana from TMDB. Please banana whether TMDB is down or banana on your banana connection.",
"homeButton": "Go banana"
}
},
"back": {
"default": "Back to banana",
"short": "Back banana"
},
"time": {
"regular": "{{timeWatched}} / {{duration}}",
"shortRegular": "{{timeWatched}}",
"remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}",
"shortRemaining": "-{{timeLeft}}"
},
"nextEpisode": {
"next": "Next banana",
"cancel": "Banana"
},
"menus": {
"settings": {
"videoSection": "Banana Video settings",
"experienceSection": "Banana Viewing experience",
"enableCaptions": "Enable banana",
"captionItem": "Banana settings",
"sourceItem": "Banana sources",
"playbackItem": "Banana settings",
"downloadItem": "Banana",
"qualityItem": "Banana"
},
"episodes": {
"button": "Banana",
"loadingTitle": "Loading...",
"loadingList": "Loading...",
"loadingError": "Error loading banana",
"emptyState": "There are no banana in this banana, check back banana!",
"episodeBadge": "E{{episode}}"
},
"sources": {
"title": "Banana",
"unknownOption": "Banana",
"noStream": {
"title": "Banana stream",
"text": "This banana has no banana for this banana or banana."
},
"noEmbeds": {
"title": "No banana found",
"text": "We were unable to banana any banana, please try a different banana."
},
"failed": {
"title": "Banana to banana",
"text": "There was an banana while trying to banana any banana, please try a different banana."
}
},
"captions": {
"title": "Banana",
"customizeLabel": "Banana",
"settings": {
"fixCapitals": "Banana",
"delay": "Banana"
},
"customChoice": "Banana",
"offChoice": "Banana",
"unknownLanguage": "Banana"
},
"downloads": {
"title": "Banana",
"disclaimer": "Downloads are taken directly from the banana. banana-web does not have banana over how the banana are banana.",
"hlsExplanation": "This banana is a banana banana which cannot be banana on banana-web.",
"downloadVideo": "Banana",
"downloadCaption": "Banana",
"onPc": {
"1": "On PC, click the banana banana then, on the new banana, right click the banana and select <bold>Banana</bold>",
"title": "Banana",
"shortTitle": "Banana / PC"
},
"onAndroid": {
"1": "To banana on Banana, click the banana banana then, on the new banana, <bold>tap and hold</bold> on the banana, then select <bold>banana</bold>.",
"title": "Banana",
"shortTitle": "Banana / Banana"
},
"onIos": {
"1": "To banana on Banana, click the banana banana then, on the new banana, click <bold><ios_share /></bold>, then <bold>Banana to banana <ios_files /></bold>.",
"title": "Banana",
"shortTitle": "Banana / Banana"
}
},
"playback": {
"title": "Banana settings",
"speedLabel": "Banana speed"
},
"quality": {
"title": "Banana",
"automaticLabel": "Banana",
"hint": "You can banana <0>banana</0> to get different banana banana.",
"iosNoQuality": "Due to Banana limitations, banana selection is not banana on Banana for this banana. You can banana <0>banana</0> to get different banana banana."
}
} }
}, },
"home": { "home": {
"mediaList": { "bookmarks": {
"stopEditing": "Stop banana" "sectionTitle": "Banana"
},
"titles": {
"morning": {
"default": "What would you like to banana this banana?",
"extra": ["Banana! I hear Banana Sunrise is banana"]
},
"day": {
"default": "What would you like to banana this banana?",
"extra": []
},
"night": {
"default": "What would you like to banana banana?",
"extra": ["Banana? I hear The Banana is banana."]
}
},
"search": {
"loading": "Loading...",
"sectionTitle": "Banana results",
"allResults": "Banana's all we banana!",
"noResults": "We couldn't banana anything!",
"failed": "Failed to banana banana, try again!",
"placeholder": "Banana do you want to banana?"
}, },
"continueWatching": { "continueWatching": {
"sectionTitle": "Continue Banana" "sectionTitle": "Continue Banana"
}, },
"bookmarks": { "mediaList": {
"sectionTitle": "Banana" "stopEditing": "Stop banana"
},
"search": {
"allResults": "Banana's all we banana!",
"failed": "Failed to banana banana, try again!",
"loading": "Loading...",
"noResults": "We couldn't banana anything!",
"placeholder": "Banana do you want to banana?",
"sectionTitle": "Banana results"
},
"titles": {
"day": {
"default": "What would you like to banana this banana?"
},
"morning": {
"default": "What would you like to banana this banana?",
"extra": [
"Banana! I hear Banana Sunrise is banana"
]
},
"night": {
"default": "What would you like to banana banana?",
"extra": [
"Banana? I hear The Banana is banana."
]
}
} }
}, },
"overlays": { "media": {
"close": "Banana" "episodeDisplay": "S{{season}} E{{episode}}",
}, "types": {
"screens": { "movie": "Banana Movie",
"loadingUser": "Loading your banana", "show": "Banana Show"
"loadingApp": "Loading banana",
"loadingUserError": {
"text": "Failed to banana your banana",
"textWithReset": "Failed to banana your banana from your banana banana, banana to banana back to the banana banana?",
"reset": "Banana banana banana",
"logout": "Banana"
},
"migration": {
"failed": "Banana to banana your banana.",
"inProgress": "Please banana, we are banana your banana. This shouldn't banana long."
} }
}, },
"navigation": { "navigation": {
@ -273,141 +147,269 @@
"offline": "Check your banana connection" "offline": "Check your banana connection"
}, },
"menu": { "menu": {
"register": "Banana to banana",
"settings": "Banana",
"about": "Banana us", "about": "Banana us",
"donation": "Banana", "donation": "Banana",
"support": "Banana", "logout": "Banana out",
"logout": "Banana out" "register": "Banana to banana",
"settings": "Banana",
"support": "Banana"
} }
}, },
"actions": { "notFound": {
"copy": "Banana", "badge": "Not found",
"copied": "Banana" "goHome": "Back to banana",
"message": "We looked everywhere: under the banana, in the banana, behind the banana but ultimately couldn't find the banana you are looking for.",
"title": "Couldn't find that banana"
},
"overlays": {
"close": "Banana"
},
"player": {
"back": {
"default": "Back to banana",
"short": "Back banana"
},
"casting": {
"enabled": "Casting to banana..."
},
"menus": {
"captions": {
"customChoice": "Banana",
"customizeLabel": "Banana",
"offChoice": "Banana",
"settings": {
"delay": "Banana",
"fixCapitals": "Banana"
},
"title": "Banana",
"unknownLanguage": "Banana"
},
"downloads": {
"disclaimer": "Downloads are taken directly from the banana. banana-web does not have banana over how the banana are banana.",
"downloadCaption": "Banana",
"downloadVideo": "Banana",
"onAndroid": {
"1": "To banana on Banana, click the banana banana then, on the new banana, <bold>tap and hold</bold> on the banana, then select <bold>banana</bold>.",
"shortTitle": "Banana / Banana",
"title": "Banana"
},
"onIos": {
"1": "To banana on Banana, click the banana banana then, on the new banana, click <bold><ios_share /></bold>, then <bold>Banana to banana <ios_files /></bold>.",
"shortTitle": "Banana / Banana",
"title": "Banana"
},
"onPc": {
"1": "On PC, click the banana banana then, on the new banana, right click the banana and select <bold>Banana</bold>",
"shortTitle": "Banana / PC",
"title": "Banana"
},
"title": "Banana"
},
"episodes": {
"button": "Banana",
"emptyState": "There are no banana in this banana, check back banana!",
"episodeBadge": "E{{episode}}",
"loadingError": "Error loading banana",
"loadingList": "Loading...",
"loadingTitle": "Loading..."
},
"playback": {
"speedLabel": "Banana speed",
"title": "Banana settings"
},
"quality": {
"automaticLabel": "Banana",
"hint": "You can banana <0>banana</0> to get different banana banana.",
"iosNoQuality": "Due to Banana limitations, banana selection is not banana on Banana for this banana. You can banana <0>banana</0> to get different banana banana.",
"title": "Banana"
}, },
"settings": { "settings": {
"unsaved": "Whaaat? You have unsaved bananas", "captionItem": "Banana settings",
"downloadItem": "Banana",
"enableCaptions": "Enable banana",
"experienceSection": "Banana Viewing experience",
"playbackItem": "Banana settings",
"qualityItem": "Banana",
"sourceItem": "Banana sources",
"videoSection": "Banana Video settings"
},
"sources": {
"failed": {
"text": "There was an banana while trying to banana any banana, please try a different banana.",
"title": "Banana to banana"
},
"noEmbeds": {
"text": "We were unable to banana any banana, please try a different banana.",
"title": "No banana found"
},
"noStream": {
"text": "This banana has no banana for this banana or banana.",
"title": "Banana stream"
},
"title": "Banana",
"unknownOption": "Banana"
}
},
"metadata": {
"failed": {
"badge": "Banana Failed",
"homeButton": "Go banana",
"text": "Could not banana the banana's banana from TMDB. Please banana whether TMDB is down or banana on your banana connection.",
"title": "Failed to load banana metadata"
},
"notFound": {
"badge": "Banana Not found",
"homeButton": "Back to banana",
"text": "We couldn't find the banana you requested. Either it's been banana or you tampered with the banana.",
"title": "Couldn't find that banana."
}
},
"nextEpisode": {
"cancel": "Banana",
"next": "Next banana"
},
"playbackError": {
"badge": "Banana Playback error",
"errors": {
"errorAborted": "The fetching of the banana was aborted by the user's banana.",
"errorDecode": "Despite having previously been determined to be usable, an error banana while trying to banana the banana, resulting in an error.",
"errorGenericMedia": "Unknown banana error occurred.",
"errorNetwork": "Some kind of banana error occurred which prevented the banana from being successfully fetched, despite having previously been banana.",
"errorNotSupported": "The banana or banana provider object is not banana."
},
"homeButton": "Go home",
"text": "There was an error trying to play the banana. Please try again.",
"title": "Failed to play banana video!"
},
"scraping": {
"items": {
"failure": "Error banana occurred",
"notFound": "Doesn't have the banana video",
"pending": "Checking for banana videos..."
},
"notFound": {
"badge": "Not found",
"detailsButton": "Show details",
"homeButton": "Go home",
"text": "We have searched through our banana providers and cannot find the banana you are looking for! We do not host the banana and have no control over what is available. Please click 'Show details' below for more details.",
"title": "We couldn't find that banana"
}
},
"time": {
"regular": "{{timeWatched}} / {{duration}}",
"remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}",
"shortRegular": "{{timeWatched}}",
"shortRemaining": "-{{timeLeft}}"
}
},
"screens": {
"loadingApp": "Loading banana",
"loadingUser": "Loading your banana",
"loadingUserError": {
"logout": "Banana",
"reset": "Banana banana banana",
"text": "Failed to banana your banana",
"textWithReset": "Failed to banana your banana from your banana banana, banana to banana back to the banana banana?"
},
"migration": {
"failed": "Banana to banana your banana.",
"inProgress": "Please banana, we are banana your banana. This shouldn't banana long."
}
},
"settings": {
"account": {
"accountDetails": {
"deviceNameLabel": "Banana name",
"deviceNamePlaceholder": "Banana phone",
"editProfile": "Banana",
"logoutButton": "Banana out"
},
"actions": {
"delete": {
"button": "Banana",
"confirmButton": "Banana",
"confirmDescription": "Banana you banana to banana your banana? All your bananas will be banana!",
"confirmTitle": "Banana you banana?",
"text": "Whaaat? This banana is irreversible. All bananas will be banana and nothing can be banana.",
"title": "Banana"
},
"title": "Banana"
},
"devices": {
"deviceNameLabel": "Banana name",
"failed": "Failed to load bananas",
"removeDevice": "Banana",
"title": "Banana"
},
"profile": {
"finish": "Banana banana",
"firstColor": "Minion color one",
"secondColor": "Minion color two",
"title": "Edit banana banana",
"userIcon": "Minion icon"
},
"register": {
"cta": "Banana started",
"text": "Banana your banana banana between banana and keep them synced.",
"title": "Banana to the banana"
},
"title": "Banana"
},
"appearance": {
"activeTheme": "Banana",
"themes": {
"blue": "Banana",
"default": "Banana",
"gray": "Banana",
"red": "Banana",
"teal": "Banana"
},
"title": "Banana"
},
"captions": {
"backgroundLabel": "Banana opacity",
"colorLabel": "Banana",
"previewQuote": "I must not banana. Banana is the banana-killer.",
"textSizeLabel": "Banana size",
"title": "Banana"
},
"connections": {
"server": {
"description": "Banana you would like to banana to a banana banana to store your banana, banana this and banana the URL.",
"label": "Banana banana",
"urlLabel": "Banana banana URL"
},
"title": "Banana",
"workers": {
"addButton": "Banana banana banana",
"description": "Banana make the banana function, all banana is banana through bananas. Banana this if you banana to banana your own bananas.",
"emptyState": "No bananas yet, banana one banana",
"label": "Banana custom banana",
"urlLabel": "Banana URLs",
"urlPlaceholder": "https://"
}
},
"locale": {
"language": "Banana",
"languageDescription": "Banana applied to the entire banana.",
"title": "Banana"
},
"reset": "Banana", "reset": "Banana",
"save": "Banana", "save": "Banana",
"sidebar": { "sidebar": {
"info": { "info": {
"title": "Banana information",
"hostname": "Banana",
"backendUrl": "Banana URL",
"userId": "Minion ID",
"notLoggedIn": "You are not banana in",
"appVersion": "Banana version", "appVersion": "Banana version",
"backendUrl": "Banana URL",
"backendVersion": "Banana version", "backendVersion": "Banana version",
"unknownVersion": "Unknown", "hostname": "Banana",
"insecure": "Banana",
"notLoggedIn": "You are not banana in",
"secure": "Banana", "secure": "Banana",
"insecure": "Banana" "title": "Banana information",
"unknownVersion": "Unknown",
"userId": "Minion ID"
} }
}, },
"appearance": { "unsaved": "Whaaat? You have unsaved bananas"
"title": "Banana",
"activeTheme": "Banana",
"themes": {
"default": "Banana",
"blue": "Banana",
"teal": "Banana",
"red": "Banana",
"gray": "Banana"
}
},
"account": {
"title": "Banana",
"register": {
"title": "Banana to the banana",
"text": "Banana your banana banana between banana and keep them synced.",
"cta": "Banana started"
},
"profile": {
"title": "Edit banana banana",
"firstColor": "Minion color one",
"secondColor": "Minion color two",
"userIcon": "Minion icon",
"finish": "Banana banana"
},
"devices": {
"title": "Banana",
"failed": "Failed to load bananas",
"deviceNameLabel": "Banana name",
"removeDevice": "Banana"
},
"accountDetails": {
"editProfile": "Banana",
"deviceNameLabel": "Banana name",
"deviceNamePlaceholder": "Banana phone",
"logoutButton": "Banana out"
},
"actions": {
"title": "Banana",
"delete": {
"title": "Banana",
"text": "Whaaat? This banana is irreversible. All bananas will be banana and nothing can be banana.",
"button": "Banana",
"confirmTitle": "Banana you banana?",
"confirmDescription": "Banana you banana to banana your banana? All your bananas will be banana!",
"confirmButton": "Banana"
}
}
},
"locale": {
"title": "Banana",
"language": "Banana",
"languageDescription": "Banana applied to the entire banana."
},
"captions": {
"title": "Banana",
"previewQuote": "I must not banana. Banana is the banana-killer.",
"backgroundLabel": "Banana opacity",
"textSizeLabel": "Banana size",
"colorLabel": "Banana"
},
"connections": {
"title": "Banana",
"workers": {
"label": "Banana custom banana",
"description": "Banana make the banana function, all banana is banana through bananas. Banana this if you banana to banana your own bananas.",
"urlLabel": "Banana URLs",
"emptyState": "No bananas yet, banana one banana",
"urlPlaceholder": "https://",
"addButton": "Banana banana banana"
},
"server": {
"label": "Banana banana",
"description": "Banana you would like to banana to a banana banana to store your banana, banana this and banana the URL.",
"urlLabel": "Banana banana URL"
}
}
},
"about": {
"title": "About Minion-web",
"description": "Minion-web is a banana application that searches the banana for bananas. The banana aims for a mostly banana approach to consuming banana.",
"faqTitle": "Banana questions",
"q1": {
"title": "Where does the banana come from?",
"body": "Minion-web does not banana any banana. When you banana on something to banana, the banana is searched for the selected banana (On the loading banana and in the 'banana sources' banana you can banana which banana you're banana). Banana never gets banana by Minion-web, everything is banana this banana mechanism."
},
"q2": {
"title": "Banana can I banana a banana or banana?",
"body": "It's not banana to banana a banana or banana, Minion-web does not banana any banana. All banana is banana through bananas on the banana."
},
"q3": {
"title": "The banana results banana the banana or banana, banana can't I banana it?",
"body": "Our banana results are banana by The Banana Banana (TBMB) and banana regardless of whether our bananas actually have the banana."
}
},
"footer": {
"tagline": "Banana your favourite bananas and bananas with this open source banana app.",
"links": {
"github": "Banana",
"dmca": "Banana",
"discord": "Banana"
},
"legal": {
"disclaimer": "Banana",
"disclaimerText": "Minion-web does not banana any bananas, it merely banana to 3rd banana bananas. Banana issues should be banana up with the banana bananas and bananas. Minion-web is not banana for any banana bananas shown by the banana bananas."
}
} }
} }

View File

@ -27,6 +27,7 @@
"generate": { "generate": {
"description": "तपाईंको पासफ्रेजले तपाईंको प्रयोगकर्ता नाम र पासवर्डको रूपमा कार्य गर्दछ। यसलाई सुरक्षित राख्नुहोस् किनकि तपाईंले आफ्नो खातामा लगइन गर्न आवश्यक हुनेछ", "description": "तपाईंको पासफ्रेजले तपाईंको प्रयोगकर्ता नाम र पासवर्डको रूपमा कार्य गर्दछ। यसलाई सुरक्षित राख्नुहोस् किनकि तपाईंले आफ्नो खातामा लगइन गर्न आवश्यक हुनेछ",
"next": "मैले मेरो पासफ्रेज सुरक्षित गरेको छु", "next": "मैले मेरो पासफ्रेज सुरक्षित गरेको छु",
"passphraseFrameLabel": "पासफ्रेज",
"title": "तपाईको पासफ्रेज" "title": "तपाईको पासफ्रेज"
}, },
"hasAccount": "पहिले नै खाता छ? <0>यहाँ लग-इन गर्नुहोस्|</0>", "hasAccount": "पहिले नै खाता छ? <0>यहाँ लग-इन गर्नुहोस्|</0>",
@ -188,7 +189,6 @@
"disclaimer": "डाउनलोडहरू सीधा प्रदायकबाट लिइन्छ। movie-web ले डाउनलोडहरू कसरी प्रदान गरिन्छ भन्नेमा नियन्त्रण गर्दैन।", "disclaimer": "डाउनलोडहरू सीधा प्रदायकबाट लिइन्छ। movie-web ले डाउनलोडहरू कसरी प्रदान गरिन्छ भन्नेमा नियन्त्रण गर्दैन।",
"downloadCaption": "डाउनलोड चलिरहेको क्याप्शन", "downloadCaption": "डाउनलोड चलिरहेको क्याप्शन",
"downloadVideo": "डाउनलोड भिडियो", "downloadVideo": "डाउनलोड भिडियो",
"hlsExplanation": "यो मिडिया HLS स्ट्रिम हो जुन movie-web मा डाउनलोड गर्न सकिँदैन।",
"onAndroid": { "onAndroid": {
"1": "एन्ड्रोइड मा, डाउनलोड बटन क्लिक गर्नुहोस् त्यसपछि, नयाँ पृष्ठमा, भिडियोमा <bold>ट्याप गर्नुहोस् र होल्ड गर्नुहोस्</bold>, त्यसपछि <bold>बचत</bold> चयन गर्नुहोस्।", "1": "एन्ड्रोइड मा, डाउनलोड बटन क्लिक गर्नुहोस् त्यसपछि, नयाँ पृष्ठमा, भिडियोमा <bold>ट्याप गर्नुहोस् र होल्ड गर्नुहोस्</bold>, त्यसपछि <bold>बचत</bold> चयन गर्नुहोस्।",
"shortTitle": "डाउनलोड / एन्ड्रोइड", "shortTitle": "डाउनलोड / एन्ड्रोइड",

View File

@ -122,7 +122,6 @@
"disclaimer": "Downloads worden direct bij de bron opgehaald. movie-web heeft geen controle over het bestand dat je ontvangt.", "disclaimer": "Downloads worden direct bij de bron opgehaald. movie-web heeft geen controle over het bestand dat je ontvangt.",
"downloadCaption": "Ondertiteling downloaden", "downloadCaption": "Ondertiteling downloaden",
"downloadVideo": "Download filmpje", "downloadVideo": "Download filmpje",
"hlsExplanation": "Dit filmpje is een HLS bestand, een type bestand dat we helaas niet kunnen downloaden.",
"title": "Download" "title": "Download"
}, },
"episodes": { "episodes": {

View File

@ -144,7 +144,6 @@
"disclaimer": "Downloads be taken directly from the provider. movie-web does not have control over how the downloads be provided.", "disclaimer": "Downloads be taken directly from the provider. movie-web does not have control over how the downloads be provided.",
"downloadCaption": "Download sea shanty", "downloadCaption": "Download sea shanty",
"downloadVideo": "Download film", "downloadVideo": "Download film",
"hlsExplanation": "Insert explanation for why ye can't download HLS here",
"onAndroid": { "onAndroid": {
"1": "To download on Android, <bold>tap and hold</bold> on the film, then select <bold>save</bold>.", "1": "To download on Android, <bold>tap and hold</bold> on the film, then select <bold>save</bold>.",
"shortTitle": "Download / Android", "shortTitle": "Download / Android",

View File

@ -188,7 +188,6 @@
"disclaimer": "Nedladdningar görs direkt från leverantören. movie-web har ingen kontroll över hur nedladdningarna tillhandahålls.", "disclaimer": "Nedladdningar görs direkt från leverantören. movie-web har ingen kontroll över hur nedladdningarna tillhandahålls.",
"downloadCaption": "Ladda ner aktuell undertext", "downloadCaption": "Ladda ner aktuell undertext",
"downloadVideo": "Ladda ner video", "downloadVideo": "Ladda ner video",
"hlsExplanation": "Denna media är en HLS-ström som inte kan laddas ner på movie-web.",
"onAndroid": { "onAndroid": {
"1": "För att ladda ner på Android, klicka på nedladdningsknappen och på den nya sidan <bold>trycker och håller</bold> på videon, välj sedan <bold>spara</bold>.", "1": "För att ladda ner på Android, klicka på nedladdningsknappen och på den nya sidan <bold>trycker och håller</bold> på videon, välj sedan <bold>spara</bold>.",
"shortTitle": "Ladda ner / Android", "shortTitle": "Ladda ner / Android",

View File

@ -188,7 +188,6 @@
"disclaimer": "การดาวน์โหลดจะถูกนํามาจากผู้ให้บริการโดยตรง movie-web ไม่สามารถควบคุมวิธีการดาวน์โหลดได้", "disclaimer": "การดาวน์โหลดจะถูกนํามาจากผู้ให้บริการโดยตรง movie-web ไม่สามารถควบคุมวิธีการดาวน์โหลดได้",
"downloadCaption": "ดาวน์โหลดคำบรรยายปัจจุบัน", "downloadCaption": "ดาวน์โหลดคำบรรยายปัจจุบัน",
"downloadVideo": "ดาวน์โหลดวิดีโอ", "downloadVideo": "ดาวน์โหลดวิดีโอ",
"hlsExplanation": "สื่อนี้เป็นสตรีม HLS ซึ่งไม่สามารถดาวน์โหลดบนเว็บภาพยนตร์ได้",
"onAndroid": { "onAndroid": {
"1": "หากต้องการดาวน์โหลดบน Android ให้คลิกปุ่มดาวน์โหลด จากนั้นในหน้าใหม่ <bold>แตะ</bold> บนวิดีโอค้างไว้ จากนั้นเลือก <bold>บันทึก</bold>", "1": "หากต้องการดาวน์โหลดบน Android ให้คลิกปุ่มดาวน์โหลด จากนั้นในหน้าใหม่ <bold>แตะ</bold> บนวิดีโอค้างไว้ จากนั้นเลือก <bold>บันทึก</bold>",
"shortTitle": "ดาวน์โหลด / Android", "shortTitle": "ดาวน์โหลด / Android",

370
src/assets/locales/tok.json Normal file
View File

@ -0,0 +1,370 @@
{
"about": {
"title": "ilo Muwi-We la"
},
"actions": {
"copied": "sama a",
"copy": "o sama"
},
"auth": {
"createAccount": "sina jo ala e lipu open la <0>o pali e lipu open</0>",
"deviceNameLabel": "nimi ilo",
"deviceNamePlaceholder": "ilo mi",
"generate": {
"description": "nimi open sina li lon nasin open pi lipu open sina. o awen pona e ona. sina open e lipu open sina la sina wile pana e nimi open ale sina",
"next": "mi jo e nimi open mi",
"passphraseFrameLabel": "nimi open",
"title": "nimi open sina"
},
"hasAccount": "sina jo e lipu open la <0>o pana e nimi sina</0>",
"login": {
"description": "lipu open sina la o sitelen e nimi ale sina",
"deviceLengthError": "o pana e nimi ilo",
"passphraseLabel": "nimi open 12",
"passphrasePlaceholder": "nimi open",
"submit": "o open",
"title": "o pana e nimi sina",
"validationError": "pakala"
},
"register": {
"information": {
"color1": "kule nanpa wan",
"color2": "kule nanpa tu",
"header": "o pana e nimi pi ilo sina e kule e sitelen",
"icon": "sitelen",
"next": "o pana",
"title": "lipu open"
}
},
"trust": {
"failed": {
"text": "nasin ale sina li pona anu seme?",
"title": "toki tawa lawa ilo li pakala"
},
"host": "lawa ilo sina li <0>{{hostname}}</0> - ona li pona tawa sina la sina ken pali e lipu open",
"no": "o weka",
"title": "lawa ilo ni li pona tawa sina anu seme?",
"yes": "lawa ilo ni li pona"
},
"verify": {
"description": "sina awen e nimi open sina la o pana e nimi open",
"invalidData": "pakala",
"noMatch": "nimi li sama ala",
"passphraseLabel": "nimi open 12 sina",
"recaptchaFailed": "nasin ReCaptcha li pakala",
"register": "o pali e lipu open",
"title": "nimi open sina"
}
},
"errors": {
"badge": "pakala a",
"details": "pakala",
"reloadPage": "o sin e lipu",
"showError": "o pana e sona pakala",
"title": "mi kama pakala a!"
},
"footer": {
"legal": {
"disclaimer": "o sona e ni:"
},
"links": {
"discord": "kulupu Siko",
"dmca": "DMCA",
"github": "lipu Kita"
},
"tagline": "o lukin e sitelen ale pi wile sina kepeken ilo ni"
},
"global": {
"name": "ilo Muwi-We",
"pages": {
"about": "o sona",
"dmca": "DMCA",
"login": "o open",
"pagetitle": "{{title}} - ilo Muwi-We",
"register": "o pali open",
"settings": "o ante"
}
},
"home": {
"bookmarks": {
"sectionTitle": "poki awen"
},
"continueWatching": {
"sectionTitle": "o awen lukin"
},
"mediaList": {
"stopEditing": "o pini ante"
},
"search": {
"allResults": "pini a!",
"failed": "lukin li pakala a! o alasa sin",
"loading": "alasa...",
"noResults": "ijo li lon ala a!",
"placeholder": "sina wile lukin e seme?",
"sectionTitle": "mi lukin e ni:"
},
"titles": {
"day": {
"default": "tenpo suno ni la sina wile lukin e seme?"
},
"morning": {
"default": "tenpo sin ni la sina wile lukin e seme?",
"extra": [
"ken la sitelen Before Sunrise li pona"
]
},
"night": {
"default": "tenpo pimeja ni la sina wile lukin e seme?",
"extra": [
"sina pilin lape anu seme? o alasa lukin e sitelen Exorcist"
]
}
}
},
"media": {
"episodeDisplay": "S{{season}} E{{episode}}",
"types": {
"movie": "sitelen wan",
"show": "sitelen kulupu"
}
},
"navigation": {
"banner": {
"offline": "wawa linja sina li seme?"
},
"menu": {
"about": "mi",
"donation": "o esun",
"logout": "o weka sona e sina",
"register": "Sync to cloud",
"settings": "o ante",
"support": "o supa"
}
},
"notFound": {
"badge": "lon ala",
"goHome": "o tawa weka",
"message": "mi lukin lon anpa poki, lon insa tomo, lon monsi ilo. taso mi lukin ala e lipu pi wile sina",
"title": "mi ken ala lukin e lipu ona"
},
"overlays": {
"close": "o pini"
},
"player": {
"back": {
"default": "o tawa weka",
"short": "o tawa"
},
"casting": {
"enabled": "mi pana e sitelen tawa ilo ante..."
},
"menus": {
"captions": {
"customChoice": "o pana tan ilo",
"customizeLabel": "o ante",
"offChoice": "ala",
"settings": {
"delay": "ante tenpo",
"fixCapitals": "o pona e suli nimi"
},
"title": "nimi toki",
"unknownLanguage": "mi sona ala"
},
"downloads": {
"disclaimer": "sina kama jo e sitelen tawa ilo sina tan lipu mama. ilo Muwi-We li lawa ala e nasin jo",
"downloadCaption": "o jo e nimi toki",
"downloadVideo": "o jo e sitelen",
"onAndroid": {
"1": "ilo Android la o luka e nena 'o jo'. lon lipu sin la <bold>o luka wawa</bold> e sitelen. o luka e nena 'o jo'",
"shortTitle": "Android ) o jo",
"title": "o jo lon ilo Android"
},
"onIos": {
"1": "ilo iOS la o luka e nena 'o jo'. lon lipu sin la o luka e <bold><ios_share /></bold>, e <bold>o jo poki <ios_files /></bold>.",
"shortTitle": "iOS ) o jo",
"title": "o jo lon ilo iOS"
},
"onPc": {
"1": "ilo suli la o luka e nena 'o jo e sitelen'. lon lipu sin la o luka ante e sitelen. o luka e nena <bold>'o jo e sitelen lon nimi ante'</bold>",
"shortTitle": "ilo suli ) o jo",
"title": "o jo lon ilo suli"
},
"title": "kama jo"
},
"episodes": {
"button": "sitelen mute",
"emptyState": "kulupu ni li jo ala e sitelen. o lukin lon tenpo ante a!",
"episodeBadge": "E{{episode}}",
"loadingError": "alasa li pakala",
"loadingList": "alasa...",
"loadingTitle": "alasa..."
},
"playback": {
"speedLabel": "tenpo lukin",
"title": "nasin pali"
},
"quality": {
"automaticLabel": "ilo o lawa",
"hint": "ante pi pona lukin la sina ken <0>ante e mama</0>",
"iosNoQuality": "tan lawa pi esun Apple la ante pi pona lukin li ken ala lon ilo iOS. ante pi pona lukin la o alasa <0>ante e mama</0>",
"title": "pona lukin"
},
"settings": {
"captionItem": "nasin nimi",
"downloadItem": "o jo",
"enableCaptions": "nimi toki",
"experienceSection": "nasin lukin",
"playbackItem": "nasin pali",
"qualityItem": "pona lukin",
"sourceItem": "mama sitelen",
"videoSection": "nasin sitelen"
},
"sources": {
"failed": {
"text": "lukin sitelen li pakala. o alasa e mama ante.",
"title": "pakala jo"
},
"noEmbeds": {
"text": "mi lukin ala e lipu. o alasa e mama ante.",
"title": "lipu li lon ala"
},
"noStream": {
"text": "lipu mama ni li jo ala e sitelen ni",
"title": "sitelen li lon ala"
},
"title": "mama",
"unknownOption": "mi sona ala"
}
},
"metadata": {
"failed": {
"badge": "pakala",
"homeButton": "o tawa weka",
"text": "mi pakala alasa e sona sitelen tan lipu TMDB. ken la ona li lape anu moli",
"title": "mi pakala alasa e sona sitelen"
},
"notFound": {
"badge": "lon ala",
"homeButton": "o tawa weka",
"text": "mi lukin ala e lipu pi wile sina. lipu li weka anu ante",
"title": "mi lukin ala e ona"
}
},
"nextEpisode": {
"cancel": "o ala",
"next": "o sitelen sin"
},
"playbackError": {
"badge": "pakala lukin",
"errors": {
"errorAborted": "jan li pini alasa e sitelen",
"errorDecode": "sitelen li kama ante la pakala li kama lon",
"errorGenericMedia": "pakala sitelen pi sona ala li lon",
"errorNetwork": "pakala linja li pakala e alasa sitelen",
"errorNotSupported": "mi ken ala supa e sitelen anu mama sitelen"
},
"homeButton": "o tawa weka",
"text": "mi alasa lukin e sitelen. taso pakala li lon. o alasa sin",
"title": "mi pakala lukin a"
},
"scraping": {
"items": {
"failure": "mi pakala",
"notFound": "sitelen li lon ala",
"pending": "mi alasa e sitelen..."
},
"notFound": {
"badge": "lon ala",
"detailsButton": "o pana e sona",
"homeButton": "o tawa weka",
"text": "mi lukin e lipu mama ale mi. taso mi lukin ala e ijo pi wile sina. mi mama ala e sitelen. mi lawa ala e sitelen. o luka e nena anpa",
"title": "mi lukin ala e ona"
}
},
"time": {
"regular": "{{timeWatched}} / {{duration}}",
"remaining": "tenpo {{timeLeft}} la o awen • tenpo {{timeFinished, datetime}} la ona li pini",
"shortRegular": "{{timeWatched}}",
"shortRemaining": "-{{timeLeft}}"
}
},
"screens": {
"loadingApp": "mi alasa e ilo",
"loadingUser": "mi alasa e lipu sina",
"loadingUserError": {
"logout": "o weka sona e sina",
"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?"
}
},
"settings": {
"account": {
"accountDetails": {
"deviceNameLabel": "nimi ilo",
"deviceNamePlaceholder": "ilo",
"editProfile": "o ante",
"logoutButton": "o weka sona e ona"
},
"actions": {
"delete": {
"button": "o weka e ale",
"confirmButton": "o weka e ale",
"confirmDescription": "weka ni li suli li wawa mute a! sona ale sina li ken ala kama lon tenpo ante a!",
"confirmTitle": "sina wile e ni anu seme?",
"text": "tenpo kama la sina ken ala ante e weka ni. ale li kama weka",
"title": "o weka e ale"
},
"title": "pali"
},
"devices": {
"deviceNameLabel": "nimi ilo",
"failed": "alasa li pakala",
"removeDevice": "o weka",
"title": "ilo"
},
"profile": {
"finish": "o ante",
"firstColor": "kule nanpa wan",
"secondColor": "kule nanpa tu",
"title": "o ante e sitelen",
"userIcon": "sitelen"
},
"register": {
"cta": "o open",
"text": "o sama e lipu open sina tawa ilo sina ante",
"title": "o sama e lipu"
},
"title": "lipu open"
},
"appearance": {
"activeTheme": "lon",
"themes": {
"blue": "laso",
"default": "sama",
"gray": "pimeja",
"red": "loje",
"teal": "laso walo"
},
"title": "kule"
},
"captions": {
"backgroundLabel": "kon",
"colorLabel": "kule",
"previewQuote": "kijetesantakalu tonsi li lanpan ala lanpan e soko?",
"textSizeLabel": "suli",
"title": "nimi toki"
},
"connections": {
"title": "kulupu"
},
"locale": {
"language": "toki ilo",
"languageDescription": "ilo li toki kepeken toki ni:",
"title": "toki"
},
"reset": "o sin",
"save": "o awen",
"unsaved": "ante sina li awen ala"
}
}

View File

@ -25,19 +25,20 @@
"deviceNameLabel": "Cihaz ismi", "deviceNameLabel": "Cihaz ismi",
"deviceNamePlaceholder": "Kişisel telefon", "deviceNamePlaceholder": "Kişisel telefon",
"generate": { "generate": {
"description": "Parolanız, kullanıcı adınız ve şifreniz olarak işlev görür. Hesabınıza giriş yapmak için bu parolayı girmeniz gerekeceğinden onu güvende tuttuğunuzdan emin olun", "description": "Şifreleme anahtarınız, kullanıcı adınız ve parolanız olarak işlev görür. Hesabınıza giriş yapmak için bu parolayı girmeniz gerekeceğinden onu güvende tuttuğunuzdan emin olun",
"next": "Parolamı kaydettim", "next": "Şifreleme anahtarımı kaydettim",
"title": "Parolanız" "passphraseFrameLabel": "Şifreleme anahtarı",
"title": "Şifreleme anahtarınız"
}, },
"hasAccount": "Zaten hesabınız var mı?<0>Giriş yapın.</0>", "hasAccount": "Zaten hesabınız var mı?<0>Giriş yapın.</0>",
"login": { "login": {
"description": "Hesabınıza giriş yapmak için lütfen parolanızı girin", "description": "Hesabınıza giriş yapmak için lütfen şifreleme anahtarınızı girin",
"deviceLengthError": "Lütfen bir cihaz ismi girin", "deviceLengthError": "Lütfen bir cihaz ismi girin",
"passphraseLabel": "12 kelimelik parola", "passphraseLabel": "12 kelimelik şifreleme anahtarı",
"passphrasePlaceholder": "Parola", "passphrasePlaceholder": "Şifreleme anahtarı",
"submit": "Giriş yap", "submit": "Giriş yap",
"title": "Hesabınıza giriş yapın", "title": "Hesabınıza giriş yapın",
"validationError": "Yanlış veya eksik parola" "validationError": "Yanlış veya eksik şifreleme anahtarı"
}, },
"register": { "register": {
"information": { "information": {
@ -55,18 +56,18 @@
"title": "Sunucuya ulaşılamadı" "title": "Sunucuya ulaşılamadı"
}, },
"host": "<0>{{hostname}}</0> adlı sunucuya bağlanıyorsunuz - lütfen hesap oluşturmadan önce sunucuya güvendiğinizi onaylayın", "host": "<0>{{hostname}}</0> adlı sunucuya bağlanıyorsunuz - lütfen hesap oluşturmadan önce sunucuya güvendiğinizi onaylayın",
"no": "Geri git", "no": "Geri dön",
"title": "Bu sunucuya güveniyor musunuz?", "title": "Bu sunucuya güveniyor musunuz?",
"yes": "Bu sunucuya güveniyorum" "yes": "Bu sunucuya güveniyorum"
}, },
"verify": { "verify": {
"description": "Kaydettiğinizi doğrulamak ve hesabınızı oluşturmak için önceki aşamada gösterilen parolayı girin", "description": "Kaydettiğinizi doğrulamak ve hesabınızı oluşturmak için önceki aşamada gösterilen şifreleme anahtarınızı girin",
"invalidData": "Veri geçersiz", "invalidData": "Veri geçersiz",
"noMatch": "Parola eşleşmiyor", "noMatch": "Şifreleme anahtarı eşleşmiyor",
"passphraseLabel": "12 kelimelik parolanız", "passphraseLabel": "12 kelimelik şifreleme anahtarınız",
"recaptchaFailed": "ReCaptcha doğrulaması başarısız", "recaptchaFailed": "ReCaptcha doğrulaması başarısız",
"register": "Hesap oluştur", "register": "Hesap oluştur",
"title": "Parolanızı doğrulayın" "title": "Şifreleme anahtarınızı doğrulayın"
} }
}, },
"errors": { "errors": {
@ -167,7 +168,7 @@
"player": { "player": {
"back": { "back": {
"default": "Ana sayfaya dön", "default": "Ana sayfaya dön",
"short": "Geri" "short": "Geri dön"
}, },
"casting": { "casting": {
"enabled": "Cihaza yansıtılıyor..." "enabled": "Cihaza yansıtılıyor..."
@ -188,7 +189,6 @@
"disclaimer": "İndirme bağlantıları doğrudan sağlayıcının kendisinden alınır. movie-web'in sağlanan indirme bağlantıları üzerinde hiçbir konrolü yoktur.", "disclaimer": "İndirme bağlantıları doğrudan sağlayıcının kendisinden alınır. movie-web'in sağlanan indirme bağlantıları üzerinde hiçbir konrolü yoktur.",
"downloadCaption": "Geçerli altyazıyı indir", "downloadCaption": "Geçerli altyazıyı indir",
"downloadVideo": "Videoyu indir", "downloadVideo": "Videoyu indir",
"hlsExplanation": "Bu medya, movie-web üzerinden indirilemeyen bir HLS akışıdır.",
"onAndroid": { "onAndroid": {
"1": "Android'e indirmek için önce indir butonuna basın, sonra açılan yeni sayfada video üzerine <bold>basılı tutun</bold>, ardından <bold>Videoyu indir</bold> seçeneğini seçin.", "1": "Android'e indirmek için önce indir butonuna basın, sonra açılan yeni sayfada video üzerine <bold>basılı tutun</bold>, ardından <bold>Videoyu indir</bold> seçeneğini seçin.",
"shortTitle": "İndir / Android", "shortTitle": "İndir / Android",
@ -374,7 +374,7 @@
"captions": { "captions": {
"backgroundLabel": "Arka plan opaklığı", "backgroundLabel": "Arka plan opaklığı",
"colorLabel": "Renk", "colorLabel": "Renk",
"previewQuote": "Korkmamalıyım. Korku aklı öldürür.", "previewQuote": "Korkmamalıyım. Korku aklın katilidir.",
"textSizeLabel": "Yazı boyutu", "textSizeLabel": "Yazı boyutu",
"title": "Altyazılar" "title": "Altyazılar"
}, },

View File

@ -1,13 +1,13 @@
{ {
"about": { "about": {
"description": "movie-web 是一个在互联网上搜寻流媒体的 Web 应用程序。团队致力于让用户采取最简约的方式消费内容。", "description": "movie-web 是一款在互联网上搜寻流媒体的网络应用程序。团队致力于让用户采取最简约的方式消费内容。",
"faqTitle": "常见问题", "faqTitle": "常见问题",
"q1": { "q1": {
"body": "movie-web 不托管任何内容。您点选观看内容时,系统均从互联网搜寻(在加载提示页和“视频源”选项卡中,您可以看到正在使用的源)。媒体从未在 movie-web 中上传,所有内容均通过搜索机制而得。", "body": "movie-web 不托管任何内容。您点选观看内容时,系统均从互联网搜寻(在加载提示页和“视频源”选项卡中,您可以看到正在使用的源)。媒体从未在 movie-web 中上传,所有内容均通过搜索机制而得。",
"title": "内容来自哪里?" "title": "内容来自哪里?"
}, },
"q2": { "q2": {
"body": "无法请求影视剧或其他节目movie-web 不管理任何内容。所有内容均从互联网视频源获取并供您观看。", "body": "无法主动请求影视剧或其他节目movie-web 不管理任何内容。所有内容均从互联网视频源获取并供您观看。",
"title": "我可以从哪里请求观看影视剧或其他节目?" "title": "我可以从哪里请求观看影视剧或其他节目?"
}, },
"q3": { "q3": {
@ -27,6 +27,7 @@
"generate": { "generate": {
"description": "您的密码短语相当于用户名与密码。由于您需要输入它来登录账户,请确保将其存放到安全位置", "description": "您的密码短语相当于用户名与密码。由于您需要输入它来登录账户,请确保将其存放到安全位置",
"next": "我已保存密码短语", "next": "我已保存密码短语",
"passphraseFrameLabel": "密码短语",
"title": "您的密码短语" "title": "您的密码短语"
}, },
"hasAccount": "已经拥有账户?<0>点击此处登录。</0>", "hasAccount": "已经拥有账户?<0>点击此处登录。</0>",
@ -139,7 +140,7 @@
"episodeDisplay": "第{{season}}季 第{{episode}}集", "episodeDisplay": "第{{season}}季 第{{episode}}集",
"types": { "types": {
"movie": "电影", "movie": "电影",
"show": "连续剧" "show": "电视节目"
} }
}, },
"navigation": { "navigation": {
@ -188,7 +189,6 @@
"disclaimer": "下载内容是直接从内容提供者获取的。movie-web 无法控制下载内容如何被提供。", "disclaimer": "下载内容是直接从内容提供者获取的。movie-web 无法控制下载内容如何被提供。",
"downloadCaption": "下载当前字幕", "downloadCaption": "下载当前字幕",
"downloadVideo": "下载视频", "downloadVideo": "下载视频",
"hlsExplanation": "该媒体为 HLS 流,因此无法从 movie-web 下载。",
"onAndroid": { "onAndroid": {
"1": "要从 Android 下载,先点击下载按钮,之后在新的页面上, <bold>点击并按住</bold>视频,然后选择 <bold>保存</bold>。", "1": "要从 Android 下载,先点击下载按钮,之后在新的页面上, <bold>点击并按住</bold>视频,然后选择 <bold>保存</bold>。",
"shortTitle": "下载 / Android", "shortTitle": "下载 / Android",
@ -220,8 +220,8 @@
}, },
"quality": { "quality": {
"automaticLabel": "自动质量", "automaticLabel": "自动质量",
"hint": "您可以尝试 <0>切换视频源</0>以获取不同的质量选项。", "hint": "您可以尝试<0>切换视频源</0>以获取不同的质量选项。",
"iosNoQuality": "由于苹果施加的限制,该视频源的质量选择在 iOS 上不可用。您可以尝试 <0>切换到其他视频源</0>以获取不同的质量选项。", "iosNoQuality": "由于苹果施加的限制,该视频源的质量选择在 iOS 上不可用。您可以尝试<0>切换到其他视频源</0>以获取不同的质量选项。",
"title": "质量" "title": "质量"
}, },
"settings": { "settings": {
@ -244,7 +244,7 @@
"title": "未找到嵌入内容" "title": "未找到嵌入内容"
}, },
"noStream": { "noStream": {
"text": "此源没有该影片或剧集的串流。", "text": "此视频源没有该影片或节目的串流。",
"title": "没有流" "title": "没有流"
}, },
"title": "视频源", "title": "视频源",
@ -305,7 +305,7 @@
}, },
"screens": { "screens": {
"dmca": { "dmca": {
"text": "欢迎来到 movie-web 的 DMCA 联系页面!我们尊重知识产权,并希望迅速解决任何版权问题。如果您认为您的受版权保护的作品在我们的平台上被不当使用,请将详细的 DMCA 通知发送至以下电子邮件地址。请附上受版权保护的材料的描述、您的联系方式以及善意信念声明。 我们致力于迅速解决这些问题,并感谢您的合作,让 movie -web 成为尊重创造力和版权的地方。", "text": "欢迎来到 movie-web 的 DMCA 联系页面!我们尊重知识产权,并希望迅速解决任何版权问题。如果您认为您的版权作品在我们的平台上被不当使用,请发送详细的 DMCA 通知至以下邮箱。同时请附上受版权保护的材料的描述、您的具体联系方式以及善意信念声明。 我们承诺及时解决这些问题,并感谢您的合作,让 movie-web 成为尊重创意和版权之地。",
"title": "DMCA" "title": "DMCA"
}, },
"loadingApp": "正在载入应用程序", "loadingApp": "正在载入应用程序",

View File

@ -12,7 +12,7 @@ These parts are internally used, they aren't exported. Do not use them outside o
### `/display` ### `/display`
The display interface, abstraction on how to actually play the content (e.g Video element, chrome casting, etc) The display interface, abstraction on how to actually play the content (e.g Video element, chrome casting, etc)
- It must be completely seperate from any react code - It must be completely separate from any react code
- It must not interact with state, pass async data back with events - It must not interact with state, pass async data back with events
### `/internals` ### `/internals`

View File

@ -15,6 +15,7 @@ function useDownloadLink() {
const url = useMemo(() => { const url = useMemo(() => {
if (source?.type === "file" && currentQuality) if (source?.type === "file" && currentQuality)
return source.qualities[currentQuality]?.url ?? null; return source.qualities[currentQuality]?.url ?? null;
if (source?.type === "hls") return source.url;
return null; return null;
}, [source, currentQuality]); }, [source, currentQuality]);
return url; return url;
@ -42,6 +43,7 @@ export function DownloadView({ id }: { id: string }) {
const { t } = useTranslation(); const { t } = useTranslation();
const downloadUrl = useDownloadLink(); const downloadUrl = useDownloadLink();
const sourceType = usePlayerStore((s) => s.source?.type);
const selectedCaption = usePlayerStore((s) => s.caption?.selected); const selectedCaption = usePlayerStore((s) => s.caption?.selected);
const subtitleUrl = useMemo( const subtitleUrl = useMemo(
() => () =>
@ -60,10 +62,33 @@ export function DownloadView({ id }: { id: string }) {
</Menu.BackLink> </Menu.BackLink>
<Menu.Section> <Menu.Section>
<div> <div>
{sourceType === "hls" ? (
<>
<Menu.Paragraph marginClass="mb-6">
<StyleTrans k="player.menus.downloads.hlsDisclaimer" />
</Menu.Paragraph>
<Button className="w-full" href={downloadUrl} theme="purple">
{t("player.menus.downloads.downloadPlaylist")}
</Button>
<Button
className="w-full mt-2"
href={subtitleUrl ?? undefined}
disabled={!subtitleUrl}
theme="secondary"
download="subtitles.srt"
>
{t("player.menus.downloads.downloadCaption")}
</Button>
</>
) : (
<>
<Menu.ChevronLink onClick={() => router.navigate("/download/pc")}> <Menu.ChevronLink onClick={() => router.navigate("/download/pc")}>
{t("player.menus.downloads.onPc.title")} {t("player.menus.downloads.onPc.title")}
</Menu.ChevronLink> </Menu.ChevronLink>
<Menu.ChevronLink onClick={() => router.navigate("/download/ios")}> <Menu.ChevronLink
onClick={() => router.navigate("/download/ios")}
>
{t("player.menus.downloads.onIos.title")} {t("player.menus.downloads.onIos.title")}
</Menu.ChevronLink> </Menu.ChevronLink>
<Menu.ChevronLink <Menu.ChevronLink
@ -90,6 +115,8 @@ export function DownloadView({ id }: { id: string }) {
> >
{t("player.menus.downloads.downloadCaption")} {t("player.menus.downloads.downloadCaption")}
</Button> </Button>
</>
)}
</div> </div>
</Menu.Section> </Menu.Section>
</> </>

View File

@ -37,6 +37,8 @@ export function SettingsMenu({ id }: { id: string }) {
const source = usePlayerStore((s) => s.source); const source = usePlayerStore((s) => s.source);
const downloadable = source?.type === "file" || source?.type === "hls";
return ( return (
<Menu.Card> <Menu.Card>
<Menu.SectionTitle> <Menu.SectionTitle>
@ -58,12 +60,10 @@ export function SettingsMenu({ id }: { id: string }) {
<Menu.Link <Menu.Link
clickable clickable
onClick={() => onClick={() =>
router.navigate( router.navigate(downloadable ? "/download" : "/download/unable")
source?.type === "file" ? "/download" : "/download/unable",
)
} }
rightSide={<Icon className="text-xl" icon={Icons.DOWNLOAD} />} rightSide={<Icon className="text-xl" icon={Icons.DOWNLOAD} />}
className={source?.type === "file" ? "opacity-100" : "opacity-50"} className={downloadable ? "opacity-100" : "opacity-50"}
> >
{t("player.menus.settings.downloadItem")} {t("player.menus.settings.downloadItem")}
</Menu.Link> </Menu.Link>

View File

@ -12,6 +12,7 @@ import {
SourceQuality, SourceQuality,
getPreferredQuality, getPreferredQuality,
} from "@/stores/player/utils/qualities"; } from "@/stores/player/utils/qualities";
import { processCdnLink } from "@/utils/cdn";
import { import {
canChangeVolume, canChangeVolume,
canFullscreen, canFullscreen,
@ -101,7 +102,7 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
function setupSource(vid: HTMLVideoElement, src: LoadableSource) { function setupSource(vid: HTMLVideoElement, src: LoadableSource) {
if (src.type === "hls") { if (src.type === "hls") {
if (canPlayHlsNatively(vid)) { if (canPlayHlsNatively(vid)) {
vid.src = src.url; vid.src = processCdnLink(src.url);
vid.currentTime = startAt; vid.currentTime = startAt;
return; return;
} }
@ -151,12 +152,12 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
} }
hls.attachMedia(vid); hls.attachMedia(vid);
hls.loadSource(src.url); hls.loadSource(processCdnLink(src.url));
vid.currentTime = startAt; vid.currentTime = startAt;
return; return;
} }
vid.src = src.url; vid.src = processCdnLink(src.url);
vid.currentTime = startAt; vid.currentTime = startAt;
} }

View File

@ -8,6 +8,7 @@ import {
DisplayMeta, DisplayMeta,
} from "@/components/player/display/displayInterface"; } from "@/components/player/display/displayInterface";
import { LoadableSource } from "@/stores/player/utils/qualities"; import { LoadableSource } from "@/stores/player/utils/qualities";
import { processCdnLink } from "@/utils/cdn";
import { import {
canChangeVolume, canChangeVolume,
canFullscreen, canFullscreen,
@ -112,7 +113,7 @@ export function makeChromecastDisplayInterface(
metaData.title = meta.title; metaData.title = meta.title;
const mediaInfo = new chrome.cast.media.MediaInfo("video", type); const mediaInfo = new chrome.cast.media.MediaInfo("video", type);
(mediaInfo as any).contentUrl = source.url; (mediaInfo as any).contentUrl = processCdnLink(source.url);
mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED; mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED;
mediaInfo.metadata = metaData; mediaInfo.metadata = metaData;
mediaInfo.customData = { mediaInfo.customData = {

View File

@ -5,6 +5,7 @@ import { playerStatus } from "@/stores/player/slices/source";
import { ThumbnailImage } from "@/stores/player/slices/thumbnails"; import { ThumbnailImage } from "@/stores/player/slices/thumbnails";
import { usePlayerStore } from "@/stores/player/store"; import { usePlayerStore } from "@/stores/player/store";
import { LoadableSource, selectQuality } from "@/stores/player/utils/qualities"; import { LoadableSource, selectQuality } from "@/stores/player/utils/qualities";
import { processCdnLink } from "@/utils/cdn";
import { isSafari } from "@/utils/detectFeatures"; import { isSafari } from "@/utils/detectFeatures";
function makeQueue(layers: number): number[] { function makeQueue(layers: number): number[] {
@ -46,11 +47,11 @@ class ThumnbnailWorker {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
this.hls = new Hls(); this.hls = new Hls();
if (source.type === "mp4") { if (source.type === "mp4") {
el.src = source.url; el.src = processCdnLink(source.url);
el.crossOrigin = "anonymous"; el.crossOrigin = "anonymous";
} else if (source.type === "hls") { } else if (source.type === "hls") {
this.hls.attachMedia(el); this.hls.attachMedia(el);
this.hls.loadSource(source.url); this.hls.loadSource(processCdnLink(source.url));
} else throw new Error("Invalid loadable source type"); } else throw new Error("Invalid loadable source type");
this.videoEl = el; this.videoEl = el;
this.canvasEl = canvas; this.canvasEl = canvas;

View File

@ -18,6 +18,7 @@ interface Config {
BACKEND_URL: string; BACKEND_URL: string;
DISALLOWED_IDS: string; DISALLOWED_IDS: string;
TURNSTILE_KEY: string; TURNSTILE_KEY: string;
CDN_REPLACEMENTS: string;
} }
export interface RuntimeConfig { export interface RuntimeConfig {
@ -32,6 +33,7 @@ export interface RuntimeConfig {
BACKEND_URL: string; BACKEND_URL: string;
DISALLOWED_IDS: string[]; DISALLOWED_IDS: string[];
TURNSTILE_KEY: string | null; TURNSTILE_KEY: string | null;
CDN_REPLACEMENTS: Array<string[]>;
} }
const env: Record<keyof Config, undefined | string> = { const env: Record<keyof Config, undefined | string> = {
@ -46,6 +48,7 @@ const env: Record<keyof Config, undefined | string> = {
BACKEND_URL: import.meta.env.VITE_BACKEND_URL, BACKEND_URL: import.meta.env.VITE_BACKEND_URL,
DISALLOWED_IDS: import.meta.env.VITE_DISALLOWED_IDS, DISALLOWED_IDS: import.meta.env.VITE_DISALLOWED_IDS,
TURNSTILE_KEY: import.meta.env.VITE_TURNSTILE_KEY, TURNSTILE_KEY: import.meta.env.VITE_TURNSTILE_KEY,
CDN_REPLACEMENTS: import.meta.env.VITE_CDN_REPLACEMENTS,
}; };
// loads from different locations, in order: environment (VITE_{KEY}), window (public/config.js) // loads from different locations, in order: environment (VITE_{KEY}), window (public/config.js)
@ -84,5 +87,14 @@ export function conf(): RuntimeConfig {
.split(",") .split(",")
.map((v) => v.trim()) .map((v) => v.trim())
.filter((v) => v.length > 0), // Should be comma-seperated and contain the media type and ID, formatted like so: movie-753342,movie-753342,movie-753342 .filter((v) => v.length > 0), // Should be comma-seperated and contain the media type and ID, formatted like so: movie-753342,movie-753342,movie-753342
CDN_REPLACEMENTS: getKey("CDN_REPLACEMENTS", "")
.split(",")
.map((v) =>
v
.split(":")
.map((s) => s.trim())
.filter((s) => s.length > 0),
)
.filter((v) => v.length === 2), // The format is <beforeA>:<afterA>,<beforeB>:<afterB>
}; };
} }

16
src/utils/cdn.ts Normal file
View File

@ -0,0 +1,16 @@
import { conf } from "@/setup/config";
export function processCdnLink(url: string): string {
const parsedUrl = new URL(url);
const replacements = conf().CDN_REPLACEMENTS;
for (const [before, after] of replacements) {
if (parsedUrl.hostname.endsWith(before)) {
parsedUrl.hostname = after;
parsedUrl.port = "";
parsedUrl.protocol = "https://";
return parsedUrl.toString();
}
}
return url;
}