From 3dfa84940273619ae00f11a5f419a5e4876b2f53 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Aug 2018 10:48:35 +0200 Subject: [PATCH] Translate subtitle langs in player --- client/src/app/core/server/server.service.ts | 4 +-- client/src/app/shared/i18n/i18n-utils.ts | 7 +--- .../video-caption/video-caption.service.ts | 27 +++++++++++---- .../video-import/video-import.service.ts | 3 +- client/src/app/shared/video/video.model.ts | 3 +- .../+video-watch/video-watch.component.ts | 4 +-- client/src/assets/player/peertube-player.ts | 34 ++++++++++++++++--- client/src/standalone/videos/embed.ts | 11 +++--- scripts/build/client.sh | 8 +++-- shared/models/i18n/i18n.ts | 4 +++ 10 files changed, 73 insertions(+), 32 deletions(-) diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index 52b50cbe8..6d886d2dd 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -7,8 +7,8 @@ import { getCompleteLocale, ServerConfig } from '../../../../../shared' import { About } from '../../../../../shared/models/server/about.model' import { environment } from '../../../environments/environment' import { VideoConstant } from '../../../../../shared/models/videos' -import { isDefaultLocale } from '../../../../../shared/models/i18n' -import { getDevLocale, isOnDevLocale, peertubeTranslate } from '@app/shared/i18n/i18n-utils' +import { isDefaultLocale, peertubeTranslate } from '../../../../../shared/models/i18n' +import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' import { sortBy } from '@app/shared/misc/utils' @Injectable() diff --git a/client/src/app/shared/i18n/i18n-utils.ts b/client/src/app/shared/i18n/i18n-utils.ts index 37180b930..1838dc752 100644 --- a/client/src/app/shared/i18n/i18n-utils.ts +++ b/client/src/app/shared/i18n/i18n-utils.ts @@ -1,9 +1,5 @@ import { environment } from '../../../environments/environment' -function peertubeTranslate (str: string, translations: { [ id: string ]: string }) { - return translations[str] ? translations[str] : str -} - function isOnDevLocale () { return environment.production === false && window.location.search === '?lang=fr' } @@ -14,6 +10,5 @@ function getDevLocale () { export { getDevLocale, - isOnDevLocale, - peertubeTranslate + isOnDevLocale } diff --git a/client/src/app/shared/video-caption/video-caption.service.ts b/client/src/app/shared/video-caption/video-caption.service.ts index 9c29bc052..994882451 100644 --- a/client/src/app/shared/video-caption/video-caption.service.ts +++ b/client/src/app/shared/video-caption/video-caption.service.ts @@ -1,29 +1,44 @@ -import { catchError, map } from 'rxjs/operators' +import { catchError, map, switchMap } from 'rxjs/operators' import { HttpClient } from '@angular/common/http' import { Injectable } from '@angular/core' import { forkJoin, Observable, of } from 'rxjs' -import { ResultList } from '../../../../../shared' +import { peertubeTranslate, ResultList } from '../../../../../shared' import { RestExtractor, RestService } from '../rest' import { VideoService } from '@app/shared/video/video.service' import { objectToFormData, sortBy } from '@app/shared/misc/utils' import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' import { VideoCaption } from '../../../../../shared/models/videos/caption/video-caption.model' +import { ServerService } from '@app/core' @Injectable() export class VideoCaptionService { constructor ( private authHttp: HttpClient, + private serverService: ServerService, private restService: RestService, private restExtractor: RestExtractor ) {} listCaptions (videoId: number | string): Observable> { return this.authHttp.get>(VideoService.BASE_VIDEO_URL + videoId + '/captions') - .pipe(map(res => { - sortBy(res.data, 'language', 'label') + .pipe( + switchMap(captionsResult => { + return this.serverService.localeObservable + .pipe(map(translations => ({ captionsResult, translations }))) + }), + map(({ captionsResult, translations }) => { + for (const c of captionsResult.data) { + c.language.label = peertubeTranslate(c.language.label, translations) + } - return res - })) + return captionsResult + }), + map(captionsResult => { + sortBy(captionsResult.data, 'language', 'label') + + return captionsResult + }) + ) .pipe(catchError(res => this.restExtractor.handleError(res))) } diff --git a/client/src/app/shared/video-import/video-import.service.ts b/client/src/app/shared/video-import/video-import.service.ts index fc34dbf2d..7ae66ddfc 100644 --- a/client/src/app/shared/video-import/video-import.service.ts +++ b/client/src/app/shared/video-import/video-import.service.ts @@ -2,7 +2,7 @@ import { catchError, map, switchMap } from 'rxjs/operators' import { HttpClient, HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' import { Observable } from 'rxjs' -import { VideoImport } from '../../../../../shared' +import { peertubeTranslate, VideoImport } from '../../../../../shared' import { environment } from '../../../environments/environment' import { RestExtractor, RestService } from '../rest' import { VideoImportCreate, VideoUpdate } from '../../../../../shared/models/videos' @@ -12,7 +12,6 @@ import { UserService } from '@app/shared/users/user.service' import { SortMeta } from 'primeng/components/common/sortmeta' import { RestPagination } from '@app/shared/rest' import { ServerService } from '@app/core' -import { peertubeTranslate } from '@app/shared/i18n/i18n-utils' @Injectable() export class VideoImportService { diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index ec0afcccb..df8253301 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -3,9 +3,8 @@ import { Video as VideoServerModel, VideoPrivacy, VideoState } from '../../../.. import { Avatar } from '../../../../../shared/models/avatars/avatar.model' import { VideoConstant } from '../../../../../shared/models/videos/video-constant.model' import { getAbsoluteAPIUrl } from '../misc/utils' -import { ServerConfig } from '../../../../../shared/models' +import { peertubeTranslate, ServerConfig } from '../../../../../shared/models' import { Actor } from '@app/shared/actor/actor.model' -import { peertubeTranslate } from '@app/shared/i18n/i18n-utils' import { VideoScheduleUpdate } from '../../../../../shared/models/videos/video-schedule-update.model' export class Video implements VideoServerModel { diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index d8230f172..5fba1b12d 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -22,7 +22,7 @@ import { VideoDownloadComponent } from './modal/video-download.component' import { VideoReportComponent } from './modal/video-report.component' import { VideoShareComponent } from './modal/video-share.component' import { VideoBlacklistComponent } from './modal/video-blacklist.component' -import { addContextMenu, getVideojsOptions, loadLocale } from '../../../assets/player/peertube-player' +import { addContextMenu, getVideojsOptions, loadLocaleInVideoJS } from '../../../assets/player/peertube-player' import { ServerService } from '@app/core' import { I18n } from '@ngx-translate/i18n-polyfill' import { environment } from '../../../environments/environment' @@ -411,7 +411,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { }) if (this.videojsLocaleLoaded === false) { - await loadLocale(environment.apiUrl, videojs, isOnDevLocale() ? getDevLocale() : this.localeId) + await loadLocaleInVideoJS(environment.apiUrl, videojs, isOnDevLocale() ? getDevLocale() : this.localeId) this.videojsLocaleLoaded = true } diff --git a/client/src/assets/player/peertube-player.ts b/client/src/assets/player/peertube-player.ts index 1fca6a7d2..1b1ec7a68 100644 --- a/client/src/assets/player/peertube-player.ts +++ b/client/src/assets/player/peertube-player.ts @@ -174,18 +174,42 @@ function addContextMenu (player: any, videoEmbedUrl: string) { }) } -function loadLocale (serverUrl: string, videojs: any, locale: string) { +function loadLocaleInVideoJS (serverUrl: string, videojs: any, locale: string) { + const path = getLocalePath(serverUrl, locale) + // It is the default locale, nothing to translate + if (!path) return Promise.resolve(undefined) + const completeLocale = getCompleteLocale(locale) - if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return Promise.resolve(undefined) - - return fetch(serverUrl + '/client/locales/' + completeLocale + '/player.json') + return fetch(path + '/player.json') .then(res => res.json()) .then(json => videojs.addLanguage(getShortLocale(completeLocale), json)) } +function getServerTranslations (serverUrl: string, locale: string) { + const path = getLocalePath(serverUrl, locale) + // It is the default locale, nothing to translate + if (!path) return Promise.resolve(undefined) + + return fetch(path + '/server.json') + .then(res => res.json()) +} + +// ############################################################################ + export { - loadLocale, + getServerTranslations, + loadLocaleInVideoJS, getVideojsOptions, addContextMenu } + +// ############################################################################ + +function getLocalePath (serverUrl: string, locale: string) { + const completeLocale = getCompleteLocale(locale) + + if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return undefined + + return serverUrl + '/client/locales/' + completeLocale +} diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index 2aabb5fe8..ea3436c7c 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -20,8 +20,8 @@ import 'whatwg-fetch' import * as vjs from 'video.js' import * as Channel from 'jschannel' -import { ResultList, VideoDetails } from '../../../../shared' -import { addContextMenu, getVideojsOptions, loadLocale } from '../../assets/player/peertube-player' +import { peertubeTranslate, ResultList, VideoDetails } from '../../../../shared' +import { addContextMenu, getServerTranslations, getVideojsOptions, loadLocaleInVideoJS } from '../../assets/player/peertube-player' import { PeerTubeResolution } from '../player/definitions' import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings' import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' @@ -257,8 +257,9 @@ class PeerTubeEmbed { const lastPart = urlParts[ urlParts.length - 1 ] const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ] - await loadLocale(window.location.origin, vjs, navigator.language) - const [ videoResponse, captionsResponse ] = await Promise.all([ + const [ , serverTranslations, videoResponse, captionsResponse ] = await Promise.all([ + loadLocaleInVideoJS(window.location.origin, vjs, navigator.language), + getServerTranslations(window.location.origin, navigator.language), this.loadVideoInfo(videoId), this.loadVideoCaptions(videoId) ]) @@ -274,7 +275,7 @@ class PeerTubeEmbed { if (captionsResponse.ok) { const { data } = (await captionsResponse.json()) as ResultList videoCaptions = data.map(c => ({ - label: c.language.label, + label: peertubeTranslate(c.language.label, serverTranslations), language: c.language.id, src: window.location.origin + c.captionPath })) diff --git a/scripts/build/client.sh b/scripts/build/client.sh index 080454d07..3d1d0234e 100755 --- a/scripts/build/client.sh +++ b/scripts/build/client.sh @@ -30,8 +30,12 @@ post_build_hook # Don't build other languages if --light arg is provided if [ -z ${1+x} ] || [ "$1" != "--light" ]; then - # Supported languages - languages=("fr_FR" "eu_ES" "ca_ES" "cs_CZ" "eo" "zh_Hant_TW" "de_DE" "es_ES" "oc") + if [ ! -z ${1+x} ] && [ "$1" == "--light-fr" ]; then + languages=("fr_FR") + else + # Supported languages + languages=("fr_FR" "eu_ES" "ca_ES" "cs_CZ" "eo" "zh_Hant_TW" "de_DE" "es_ES" "oc") + fi for lang in "${languages[@]}"; do # TODO: remove when the project will use runtime translations diff --git a/shared/models/i18n/i18n.ts b/shared/models/i18n/i18n.ts index 2530a1927..c5de972ac 100644 --- a/shared/models/i18n/i18n.ts +++ b/shared/models/i18n/i18n.ts @@ -36,6 +36,10 @@ export function isDefaultLocale (locale: string) { return getCompleteLocale(locale) === getCompleteLocale(getDefaultLocale()) } +export function peertubeTranslate (str: string, translations?: { [ id: string ]: string }) { + return translations && translations[str] ? translations[str] : str +} + const possiblePaths = POSSIBLE_LOCALES.map(l => '/' + l) export function is18nPath (path: string) { return possiblePaths.indexOf(path) !== -1