Add server localization

This commit is contained in:
Chocobozzz 2018-06-06 16:46:42 +02:00
parent f07d6385b4
commit 7ce44a74a3
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
12 changed files with 1076 additions and 467 deletions

View File

@ -1,17 +1,20 @@
import { tap } from 'rxjs/operators' import { map, share, switchMap, tap } from 'rxjs/operators'
import { HttpClient } from '@angular/common/http' import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core' import { Inject, Injectable, LOCALE_ID } from '@angular/core'
import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
import { ReplaySubject } from 'rxjs' import { Observable, ReplaySubject } from 'rxjs'
import { ServerConfig } from '../../../../../shared' import { ServerConfig } from '../../../../../shared'
import { About } from '../../../../../shared/models/server/about.model' import { About } from '../../../../../shared/models/server/about.model'
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos' import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos'
import { buildFileLocale, getDefaultLocale } from '../../../../../shared/models/i18n'
import { peertubeTranslate } from '@app/shared/i18n/i18n-utils'
@Injectable() @Injectable()
export class ServerService { export class ServerService {
private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/' private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/'
private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/'
private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/'
private static CONFIG_LOCAL_STORAGE_KEY = 'server-config' private static CONFIG_LOCAL_STORAGE_KEY = 'server-config'
configLoaded = new ReplaySubject<boolean>(1) configLoaded = new ReplaySubject<boolean>(1)
@ -19,6 +22,7 @@ export class ServerService {
videoCategoriesLoaded = new ReplaySubject<boolean>(1) videoCategoriesLoaded = new ReplaySubject<boolean>(1)
videoLicencesLoaded = new ReplaySubject<boolean>(1) videoLicencesLoaded = new ReplaySubject<boolean>(1)
videoLanguagesLoaded = new ReplaySubject<boolean>(1) videoLanguagesLoaded = new ReplaySubject<boolean>(1)
localeObservable: Observable<any>
private config: ServerConfig = { private config: ServerConfig = {
instance: { instance: {
@ -64,8 +68,12 @@ export class ServerService {
private videoLanguages: Array<VideoConstant<string>> = [] private videoLanguages: Array<VideoConstant<string>> = []
private videoPrivacies: Array<VideoConstant<VideoPrivacy>> = [] private videoPrivacies: Array<VideoConstant<VideoPrivacy>> = []
constructor (private http: HttpClient) { constructor (
private http: HttpClient,
@Inject(LOCALE_ID) private localeId: string
) {
this.loadConfigLocally() this.loadConfigLocally()
this.loadServerLocale()
} }
loadConfig () { loadConfig () {
@ -124,26 +132,46 @@ export class ServerService {
notifier: ReplaySubject<boolean>, notifier: ReplaySubject<boolean>,
sort = false sort = false
) { ) {
return this.http.get(ServerService.BASE_VIDEO_URL + attributeName) this.localeObservable
.subscribe(data => { .pipe(
Object.keys(data) switchMap(translations => {
.forEach(dataKey => { return this.http.get(ServerService.BASE_VIDEO_URL + attributeName)
hashToPopulate.push({ .pipe(map(data => ({ data, translations })))
id: dataKey, })
label: data[dataKey] )
}) .subscribe(({ data, translations }) => {
}) Object.keys(data)
.forEach(dataKey => {
const label = data[ dataKey ]
if (sort === true) { hashToPopulate.push({
hashToPopulate.sort((a, b) => { id: dataKey,
if (a.label < b.label) return -1 label: peertubeTranslate(label, translations)
if (a.label === b.label) return 0 })
return 1 })
})
}
notifier.next(true) if (sort === true) {
}) hashToPopulate.sort((a, b) => {
if (a.label < b.label) return -1
if (a.label === b.label) return 0
return 1
})
}
notifier.next(true)
})
}
private loadServerLocale () {
const fileLocale = buildFileLocale(environment.production === true ? this.localeId : 'fr')
// Default locale, nothing to translate
const defaultFileLocale = buildFileLocale(getDefaultLocale())
if (fileLocale === defaultFileLocale) return {}
this.localeObservable = this.http
.get(ServerService.BASE_LOCALE_URL + fileLocale + '/server.json')
.pipe(share())
} }
private saveConfigLocally (config: ServerConfig) { private saveConfigLocally (config: ServerConfig) {

View File

@ -0,0 +1,7 @@
function peertubeTranslate (str: string, translations: { [ id: string ]: string }) {
return translations[str] ? translations[str] : str
}
export {
peertubeTranslate
}

View File

@ -15,8 +15,8 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
likesPercent: number likesPercent: number
dislikesPercent: number dislikesPercent: number
constructor (hash: VideoDetailsServerModel) { constructor (hash: VideoDetailsServerModel, translations = {}) {
super(hash) super(hash, translations)
this.descriptionPath = hash.descriptionPath this.descriptionPath = hash.descriptionPath
this.files = hash.files this.files = hash.files

View File

@ -5,6 +5,7 @@ import { VideoConstant } from '../../../../../shared/models/videos/video.model'
import { getAbsoluteAPIUrl } from '../misc/utils' import { getAbsoluteAPIUrl } from '../misc/utils'
import { ServerConfig } from '../../../../../shared/models' import { ServerConfig } from '../../../../../shared/models'
import { Actor } from '@app/shared/actor/actor.model' import { Actor } from '@app/shared/actor/actor.model'
import { peertubeTranslate } from '@app/shared/i18n/i18n-utils'
export class Video implements VideoServerModel { export class Video implements VideoServerModel {
by: string by: string
@ -68,7 +69,7 @@ export class Video implements VideoServerModel {
minutes.toString() + ':' + secondsPadding + seconds.toString() minutes.toString() + ':' + secondsPadding + seconds.toString()
} }
constructor (hash: VideoServerModel) { constructor (hash: VideoServerModel, translations = {}) {
const absoluteAPIUrl = getAbsoluteAPIUrl() const absoluteAPIUrl = getAbsoluteAPIUrl()
this.createdAt = new Date(hash.createdAt.toString()) this.createdAt = new Date(hash.createdAt.toString())
@ -98,6 +99,11 @@ export class Video implements VideoServerModel {
this.by = Actor.CREATE_BY_STRING(hash.account.name, hash.account.host) this.by = Actor.CREATE_BY_STRING(hash.account.name, hash.account.host)
this.accountAvatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.account) this.accountAvatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.account)
this.category.label = peertubeTranslate(this.category.label, translations)
this.licence.label = peertubeTranslate(this.licence.label, translations)
this.language.label = peertubeTranslate(this.language.label, translations)
this.privacy.label = peertubeTranslate(this.privacy.label, translations)
} }
isVideoNSFWForUser (user: User, serverConfig: ServerConfig) { isVideoNSFWForUser (user: User, serverConfig: ServerConfig) {

View File

@ -1,4 +1,4 @@
import { catchError, map } from 'rxjs/operators' import { catchError, map, switchMap } from 'rxjs/operators'
import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http' import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
@ -24,6 +24,7 @@ import { Account } from '@app/shared/account/account.model'
import { AccountService } from '@app/shared/account/account.service' import { AccountService } from '@app/shared/account/account.service'
import { VideoChannel } from '../../../../../shared/models/videos' import { VideoChannel } from '../../../../../shared/models/videos'
import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
import { ServerService } from '@app/core'
@Injectable() @Injectable()
export class VideoService { export class VideoService {
@ -33,7 +34,8 @@ export class VideoService {
constructor ( constructor (
private authHttp: HttpClient, private authHttp: HttpClient,
private restExtractor: RestExtractor, private restExtractor: RestExtractor,
private restService: RestService private restService: RestService,
private serverService: ServerService
) {} ) {}
getVideoViewUrl (uuid: string) { getVideoViewUrl (uuid: string) {
@ -41,9 +43,13 @@ export class VideoService {
} }
getVideo (uuid: string): Observable<VideoDetails> { getVideo (uuid: string): Observable<VideoDetails> {
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid) return this.serverService.localeObservable
.pipe( .pipe(
map(videoHash => new VideoDetails(videoHash)), switchMap(translations => {
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid)
.pipe(map(videoHash => ({ videoHash, translations })))
}),
map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -102,9 +108,10 @@ export class VideoService {
let params = new HttpParams() let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
return this.authHttp.get(UserService.BASE_USERS_URL + '/me/videos', { params }) return this.authHttp
.get<ResultList<Video>>(UserService.BASE_USERS_URL + '/me/videos', { params })
.pipe( .pipe(
map(this.extractVideos), switchMap(res => this.extractVideos(res)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -120,9 +127,9 @@ export class VideoService {
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
return this.authHttp return this.authHttp
.get(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params }) .get<ResultList<Video>>(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params })
.pipe( .pipe(
map(this.extractVideos), switchMap(res => this.extractVideos(res)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -138,9 +145,9 @@ export class VideoService {
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
return this.authHttp return this.authHttp
.get(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.uuid + '/videos', { params }) .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.uuid + '/videos', { params })
.pipe( .pipe(
map(this.extractVideos), switchMap(res => this.extractVideos(res)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -160,9 +167,9 @@ export class VideoService {
} }
return this.authHttp return this.authHttp
.get(VideoService.BASE_VIDEO_URL, { params }) .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
.pipe( .pipe(
map(this.extractVideos), switchMap(res => this.extractVideos(res)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -230,7 +237,7 @@ export class VideoService {
return this.authHttp return this.authHttp
.get<ResultList<VideoServerModel>>(url, { params }) .get<ResultList<VideoServerModel>>(url, { params })
.pipe( .pipe(
map(this.extractVideos), switchMap(res => this.extractVideos(res)),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))
) )
} }
@ -287,14 +294,19 @@ export class VideoService {
} }
private extractVideos (result: ResultList<VideoServerModel>) { private extractVideos (result: ResultList<VideoServerModel>) {
const videosJson = result.data return this.serverService.localeObservable
const totalVideos = result.total .pipe(
const videos = [] map(translations => {
const videosJson = result.data
const totalVideos = result.total
const videos: Video[] = []
for (const videoJson of videosJson) { for (const videoJson of videosJson) {
videos.push(new Video(videoJson)) videos.push(new Video(videoJson, translations))
} }
return { videos, totalVideos } return { videos, totalVideos }
})
)
} }
} }

View File

@ -0,0 +1,878 @@
<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file original="namespace1" datatype="plaintext" source-language="undefined" target-language="undefined">
<body>
<trans-unit id="Music">
<source>Music</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Films">
<source>Films</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Vehicles">
<source>Vehicles</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Art">
<source>Art</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sports">
<source>Sports</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Travels">
<source>Travels</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Gaming">
<source>Gaming</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="People">
<source>People</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Comedy">
<source>Comedy</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Entertainment">
<source>Entertainment</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="News">
<source>News</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="How To">
<source>How To</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Education">
<source>Education</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Activism">
<source>Activism</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Science &amp; Technology">
<source>Science &amp; Technology</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Animals">
<source>Animals</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kids">
<source>Kids</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Food">
<source>Food</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution">
<source>Attribution</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution - Share Alike">
<source>Attribution - Share Alike</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution - No Derivatives">
<source>Attribution - No Derivatives</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution - Non Commercial">
<source>Attribution - Non Commercial</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution - Non Commercial - Share Alike">
<source>Attribution - Non Commercial - Share Alike</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Attribution - Non Commercial - No Derivatives">
<source>Attribution - Non Commercial - No Derivatives</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Public Domain Dedication">
<source>Public Domain Dedication</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Public">
<source>Public</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Unlisted">
<source>Unlisted</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Private">
<source>Private</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Afar">
<source>Afar</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Abkhazian">
<source>Abkhazian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Afrikaans">
<source>Afrikaans</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Akan">
<source>Akan</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Amharic">
<source>Amharic</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Arabic">
<source>Arabic</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Aragonese">
<source>Aragonese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="American Sign Language">
<source>American Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Assamese">
<source>Assamese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Avaric">
<source>Avaric</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Aymara">
<source>Aymara</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Azerbaijani">
<source>Azerbaijani</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bashkir">
<source>Bashkir</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bambara">
<source>Bambara</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Belarusian">
<source>Belarusian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bengali">
<source>Bengali</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="British Sign Language">
<source>British Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bislama">
<source>Bislama</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tibetan">
<source>Tibetan</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bosnian">
<source>Bosnian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Breton">
<source>Breton</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Bulgarian">
<source>Bulgarian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Brazilian Sign Language">
<source>Brazilian Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Catalan">
<source>Catalan</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Czech">
<source>Czech</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Chamorro">
<source>Chamorro</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Chechen">
<source>Chechen</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Chuvash">
<source>Chuvash</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Cornish">
<source>Cornish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Corsican">
<source>Corsican</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Cree">
<source>Cree</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Czech Sign Language">
<source>Czech Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Chinese Sign Language">
<source>Chinese Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Welsh">
<source>Welsh</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Danish">
<source>Danish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="German">
<source>German</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Dhivehi">
<source>Dhivehi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Danish Sign Language">
<source>Danish Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Dzongkha">
<source>Dzongkha</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Modern Greek (1453-)">
<source>Modern Greek (1453-)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="English">
<source>English</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Estonian">
<source>Estonian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Basque">
<source>Basque</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ewe">
<source>Ewe</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Faroese">
<source>Faroese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Persian">
<source>Persian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Fijian">
<source>Fijian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Finnish">
<source>Finnish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="French">
<source>French</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Western Frisian">
<source>Western Frisian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="French Sign Language">
<source>French Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Fulah">
<source>Fulah</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Scottish Gaelic">
<source>Scottish Gaelic</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Irish">
<source>Irish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Galician">
<source>Galician</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Manx">
<source>Manx</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Guarani">
<source>Guarani</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="German Sign Language">
<source>German Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Gujarati">
<source>Gujarati</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Haitian">
<source>Haitian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Hausa">
<source>Hausa</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Serbo-Croatian">
<source>Serbo-Croatian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Hebrew">
<source>Hebrew</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Herero">
<source>Herero</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Hindi">
<source>Hindi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Hiri Motu">
<source>Hiri Motu</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Croatian">
<source>Croatian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Hungarian">
<source>Hungarian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Armenian">
<source>Armenian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Igbo">
<source>Igbo</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sichuan Yi">
<source>Sichuan Yi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Inuktitut">
<source>Inuktitut</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Indonesian">
<source>Indonesian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Inupiaq">
<source>Inupiaq</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Icelandic">
<source>Icelandic</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Italian">
<source>Italian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Javanese">
<source>Javanese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Japanese">
<source>Japanese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Japanese Sign Language">
<source>Japanese Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kalaallisut">
<source>Kalaallisut</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kannada">
<source>Kannada</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kashmiri">
<source>Kashmiri</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Georgian">
<source>Georgian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kanuri">
<source>Kanuri</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kazakh">
<source>Kazakh</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Khmer">
<source>Khmer</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kikuyu">
<source>Kikuyu</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kinyarwanda">
<source>Kinyarwanda</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kirghiz">
<source>Kirghiz</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Komi">
<source>Komi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kongo">
<source>Kongo</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Korean">
<source>Korean</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kuanyama">
<source>Kuanyama</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Kurdish">
<source>Kurdish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Lao">
<source>Lao</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Latvian">
<source>Latvian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Limburgan">
<source>Limburgan</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Lingala">
<source>Lingala</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Lithuanian">
<source>Lithuanian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Luxembourgish">
<source>Luxembourgish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Luba-Katanga">
<source>Luba-Katanga</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ganda">
<source>Ganda</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Marshallese">
<source>Marshallese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Malayalam">
<source>Malayalam</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Marathi">
<source>Marathi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Macedonian">
<source>Macedonian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Malagasy">
<source>Malagasy</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Maltese">
<source>Maltese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Mongolian">
<source>Mongolian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Maori">
<source>Maori</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Malay (macrolanguage)">
<source>Malay (macrolanguage)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Burmese">
<source>Burmese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Nauru">
<source>Nauru</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Navajo">
<source>Navajo</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="South Ndebele">
<source>South Ndebele</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="North Ndebele">
<source>North Ndebele</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ndonga">
<source>Ndonga</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Nepali (macrolanguage)">
<source>Nepali (macrolanguage)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Dutch">
<source>Dutch</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Norwegian Nynorsk">
<source>Norwegian Nynorsk</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Norwegian Bokmål">
<source>Norwegian Bokmål</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Norwegian">
<source>Norwegian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Nyanja">
<source>Nyanja</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Occitan (post 1500)">
<source>Occitan (post 1500)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ojibwa">
<source>Ojibwa</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Oriya (macrolanguage)">
<source>Oriya (macrolanguage)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Oromo">
<source>Oromo</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ossetian">
<source>Ossetian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Panjabi">
<source>Panjabi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Pakistan Sign Language">
<source>Pakistan Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Polish">
<source>Polish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Portuguese">
<source>Portuguese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Pushto">
<source>Pushto</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Quechua">
<source>Quechua</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Romansh">
<source>Romansh</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Romanian">
<source>Romanian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Russian Sign Language">
<source>Russian Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Rundi">
<source>Rundi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Russian">
<source>Russian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sango">
<source>Sango</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Saudi Arabian Sign Language">
<source>Saudi Arabian Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="South African Sign Language">
<source>South African Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sinhala">
<source>Sinhala</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Slovak">
<source>Slovak</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Slovenian">
<source>Slovenian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Northern Sami">
<source>Northern Sami</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Samoan">
<source>Samoan</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Shona">
<source>Shona</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sindhi">
<source>Sindhi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Somali">
<source>Somali</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Southern Sotho">
<source>Southern Sotho</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Spanish">
<source>Spanish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Albanian">
<source>Albanian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sardinian">
<source>Sardinian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Serbian">
<source>Serbian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Swati">
<source>Swati</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Sundanese">
<source>Sundanese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Swahili (macrolanguage)">
<source>Swahili (macrolanguage)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Swedish">
<source>Swedish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Swedish Sign Language">
<source>Swedish Sign Language</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tahitian">
<source>Tahitian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tamil">
<source>Tamil</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tatar">
<source>Tatar</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Telugu">
<source>Telugu</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tajik">
<source>Tajik</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tagalog">
<source>Tagalog</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Thai">
<source>Thai</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tigrinya">
<source>Tigrinya</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tonga (Tonga Islands)">
<source>Tonga (Tonga Islands)</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tswana">
<source>Tswana</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Tsonga">
<source>Tsonga</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Turkmen">
<source>Turkmen</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Turkish">
<source>Turkish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Twi">
<source>Twi</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Uighur">
<source>Uighur</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Ukrainian">
<source>Ukrainian</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Urdu">
<source>Urdu</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Uzbek">
<source>Uzbek</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Venda">
<source>Venda</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Vietnamese">
<source>Vietnamese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Walloon">
<source>Walloon</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Wolof">
<source>Wolof</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Xhosa">
<source>Xhosa</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Yiddish">
<source>Yiddish</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Yoruba">
<source>Yoruba</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Zhuang">
<source>Zhuang</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Chinese">
<source>Chinese</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Zulu">
<source>Zulu</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Misc">
<source>Misc</source>
<target>undefined</target>
</trans-unit>
<trans-unit id="Unknown">
<source>Unknown</source>
<target>undefined</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -1,379 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--XLIFF document generated by Zanata. Visit http://zanata.org for more infomation.-->
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" xmlns:xyz="urn:appInfo:Items" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd" version="1.1">
<file source-language="en-US" datatype="plaintext" original="" target-language="fr">
<body>
<trans-unit id="Audio Player">
<source>Audio Player</source>
<target>Lecteur audio</target>
</trans-unit>
<trans-unit id="Video Player">
<source>Video Player</source>
<target>Lecteur vidéo</target>
</trans-unit>
<trans-unit id="Play">
<source>Play</source>
<target>Lecture</target>
</trans-unit>
<trans-unit id="Pause">
<source>Pause</source>
<target>Pause</target>
</trans-unit>
<trans-unit id="Replay">
<source>Replay</source>
<target>Revoir</target>
</trans-unit>
<trans-unit id="Current Time">
<source>Current Time</source>
<target>Temps actuel</target>
</trans-unit>
<trans-unit id="Duration">
<source>Duration</source>
<target>Durée</target>
</trans-unit>
<trans-unit id="Remaining Time">
<source>Remaining Time</source>
<target>Temps restant</target>
</trans-unit>
<trans-unit id="Stream Type">
<source>Stream Type</source>
<target>Type de flux</target>
</trans-unit>
<trans-unit id="LIVE">
<source>LIVE</source>
<target>EN DIRECT</target>
</trans-unit>
<trans-unit id="Loaded">
<source>Loaded</source>
<target>Chargé</target>
</trans-unit>
<trans-unit id="Progress">
<source>Progress</source>
<target>Progression</target>
</trans-unit>
<trans-unit id="Progress Bar">
<source>Progress Bar</source>
<target>Barre de progression</target>
</trans-unit>
<trans-unit id="progress bar timing: currentTime={1} duration={2}">
<source>{1} of {2}</source>
<target>{1} de {2}</target>
</trans-unit>
<trans-unit id="Fullscreen">
<source>Fullscreen</source>
<target>Plein écran</target>
</trans-unit>
<trans-unit id="Non-Fullscreen">
<source>Non-Fullscreen</source>
<target>Fenêtré</target>
</trans-unit>
<trans-unit id="Mute">
<source>Mute</source>
<target>Sourdine</target>
</trans-unit>
<trans-unit id="Unmute">
<source>Unmute</source>
<target>Son activé</target>
</trans-unit>
<trans-unit id="Playback Rate">
<source>Playback Rate</source>
<target>Vitesse de lecture</target>
</trans-unit>
<trans-unit id="Subtitles">
<source>Subtitles</source>
<target>Sous-titres</target>
</trans-unit>
<trans-unit id="subtitles off">
<source>subtitles off</source>
<target>Sous-titres désactivés</target>
</trans-unit>
<trans-unit id="Captions">
<source>Captions</source>
<target>Sous-titres transcrits</target>
</trans-unit>
<trans-unit id="captions off">
<source>captions off</source>
<target>Sous-titres transcrits désactivés</target>
</trans-unit>
<trans-unit id="Chapters">
<source>Chapters</source>
<target>Chapitres</target>
</trans-unit>
<trans-unit id="Descriptions">
<source>Descriptions</source>
<target>Descriptions</target>
</trans-unit>
<trans-unit id="descriptions off">
<source>descriptions off</source>
<target>descriptions désactivées</target>
</trans-unit>
<trans-unit id="Audio Track">
<source>Audio Track</source>
<target>Piste audio</target>
</trans-unit>
<trans-unit id="Volume Level">
<source>Volume Level</source>
<target>Niveau de volume</target>
</trans-unit>
<trans-unit id="You aborted the media playback">
<source>You aborted the media playback</source>
<target>Vous avez interrompu la lecture de la vidéo.</target>
</trans-unit>
<trans-unit id="A network error caused the media download to fail part-way.">
<source>A network error caused the media download to fail part-way.</source>
<target>Une erreur de réseau a interrompu le téléchargement de la vidéo.</target>
</trans-unit>
<trans-unit id="The media could not be loaded, either because the server or network failed or because the format is not supported.">
<source>The media could not be loaded, either because the server or network failed or because the format is not supported.</source>
<target>Cette vidéo n'a pas pu être chargée, soit parce que le serveur ou le réseau a échoué ou parce que le format n'est pas reconnu.</target>
</trans-unit>
<trans-unit id="The media playback was aborted due to a corruption problem or because the media used features your browser did not support.">
<source>The media playback was aborted due to a corruption problem or because the media used features your browser did not support.</source>
<target>La lecture de la vidéo a été interrompue à cause d'un problème de corruption ou parce que la vidéo utilise des fonctionnalités non prises en charge par votre navigateur.</target>
</trans-unit>
<trans-unit id="No compatible source was found for this media.">
<source>No compatible source was found for this media.</source>
<target>Aucune source compatible n'a été trouvée pour cette vidéo.</target>
</trans-unit>
<trans-unit id="The media is encrypted and we do not have the keys to decrypt it.">
<source>The media is encrypted and we do not have the keys to decrypt it.</source>
<target>Le média est chiffré et nous n'avons pas les clés pour le déchiffrer.</target>
</trans-unit>
<trans-unit id="Play Video">
<source>Play Video</source>
<target>Lire la vidéo</target>
</trans-unit>
<trans-unit id="Close">
<source>Close</source>
<target>Fermer</target>
</trans-unit>
<trans-unit id="Close Modal Dialog">
<source>Close Modal Dialog</source>
<target>Fermer la boîte de dialogue modale</target>
</trans-unit>
<trans-unit id="Modal Window">
<source>Modal Window</source>
<target>Fenêtre modale</target>
</trans-unit>
<trans-unit id="This is a modal window">
<source>This is a modal window</source>
<target>Ceci est une fenêtre modale</target>
</trans-unit>
<trans-unit id="This modal can be closed by pressing the Escape key or activating the close button.">
<source>This modal can be closed by pressing the Escape key or activating the close button.</source>
<target>Ce modal peut être fermé en appuyant sur la touche Échap ou activer le bouton de fermeture.</target>
</trans-unit>
<trans-unit id=", opens captions settings dialog">
<source>, opens captions settings dialog</source>
<target>, ouvrir les paramètres des sous-titres transcrits</target>
</trans-unit>
<trans-unit id=", opens subtitles settings dialog">
<source>, opens subtitles settings dialog</source>
<target>, ouvrir les paramètres des sous-titres</target>
</trans-unit>
<trans-unit id=", opens descriptions settings dialog">
<source>, opens descriptions settings dialog</source>
<target>, ouvrir les paramètres des descriptions</target>
</trans-unit>
<trans-unit id=", selected">
<source>, selected</source>
<target>, sélectionné</target>
</trans-unit>
<trans-unit id="captions settings">
<source>captions settings</source>
<target>Paramètres des sous-titres transcrits</target>
</trans-unit>
<trans-unit id="subtitles settings">
<source>subititles settings</source>
<target>Paramètres des sous-titres</target>
</trans-unit>
<trans-unit id="descriptions settings">
<source>descriptions settings</source>
<target>Paramètres des descriptions</target>
</trans-unit>
<trans-unit id="Text">
<source>Text</source>
<target>Texte</target>
</trans-unit>
<trans-unit id="White">
<source>White</source>
<target>Blanc</target>
</trans-unit>
<trans-unit id="Black">
<source>Black</source>
<target>Noir</target>
</trans-unit>
<trans-unit id="Red">
<source>Red</source>
<target>Rouge</target>
</trans-unit>
<trans-unit id="Green">
<source>Green</source>
<target>Vert</target>
</trans-unit>
<trans-unit id="Blue">
<source>Blue</source>
<target>Bleu</target>
</trans-unit>
<trans-unit id="Yellow">
<source>Yellow</source>
<target>Jaune</target>
</trans-unit>
<trans-unit id="Magenta">
<source>Magenta</source>
<target>Magenta</target>
</trans-unit>
<trans-unit id="Cyan">
<source>Cyan</source>
<target>Cyan</target>
</trans-unit>
<trans-unit id="Background">
<source>Background</source>
<target>Arrière-plan</target>
</trans-unit>
<trans-unit id="Window">
<source>Window</source>
<target>Fenêtre</target>
</trans-unit>
<trans-unit id="Transparent">
<source>Transparent</source>
<target>Transparent</target>
</trans-unit>
<trans-unit id="Semi-Transparent">
<source>Semi-Transparent</source>
<target>Semi-transparent</target>
</trans-unit>
<trans-unit id="Opaque">
<source>Opaque</source>
<target>Opaque</target>
</trans-unit>
<trans-unit id="Font Size">
<source>Font Size</source>
<target>Taille des caractères</target>
</trans-unit>
<trans-unit id="Text Edge Style">
<source>Text Edge Style</source>
<target>Style des contours du texte</target>
</trans-unit>
<trans-unit id="None">
<source>None</source>
<target>Aucun</target>
</trans-unit>
<trans-unit id="Raised">
<source>Raised</source>
<target>Élevé</target>
</trans-unit>
<trans-unit id="Depressed">
<source>Depressed</source>
<target>Enfoncé</target>
</trans-unit>
<trans-unit id="Uniform">
<source>Uniform</source>
<target>Uniforme</target>
</trans-unit>
<trans-unit id="Dropshadow">
<source>Dropshadow</source>
<target>Ombre portée</target>
</trans-unit>
<trans-unit id="Font Family">
<source>Font Family</source>
<target>Familles de polices</target>
</trans-unit>
<trans-unit id="Proportional Sans-Serif">
<source>Proportional Sans-Serif</source>
<target>Polices à chasse variable sans empattement (Proportional Sans-Serif)</target>
</trans-unit>
<trans-unit id="Monospace Sans-Serif">
<source>Monospace Sans-Serif</source>
<target>Polices à chasse fixe sans empattement (Monospace Sans-Serif)</target>
</trans-unit>
<trans-unit id="Proportional Serif">
<source>Proportional Serif</source>
<target>Polices à chasse variable avec empattement (Proportional Serif)</target>
</trans-unit>
<trans-unit id="Monospace Serif">
<source>Monospace Serif</source>
<target>Polices à chasse fixe avec empattement (Monospace Serif)</target>
</trans-unit>
<trans-unit id="Casual">
<source>Casual</source>
<target>Manuscrite</target>
</trans-unit>
<trans-unit id="Script">
<source>Script</source>
<target>Scripte</target>
</trans-unit>
<trans-unit id="Small Caps">
<source>Small Caps</source>
<target>Petites capitales</target>
</trans-unit>
<trans-unit id="Reset">
<source>Reset</source>
<target>Réinitialiser</target>
</trans-unit>
<trans-unit id="restore all settings to the default values">
<source>restore all settings to the default values</source>
<target>Restaurer tous les paramètres aux valeurs par défaut</target>
</trans-unit>
<trans-unit id="Done">
<source>Done</source>
<target>Terminé</target>
</trans-unit>
<trans-unit id="Caption Settings Dialog">
<source>Caption Settings Dialog</source>
<target>Boîte de dialogue des paramètres des sous-titres transcrits</target>
</trans-unit>
<trans-unit id="Beginning of dialog window. Escape will cancel and close the window.">
<source>Beginning of dialog window. Escape will cancel and close the window.</source>
<target>Début de la fenêtre de dialogue. La touche d'échappement annulera et fermera la fenêtre.</target>
</trans-unit>
<trans-unit id="End of dialog window.">
<source>End of dialog window.</source>
<target>Fin de la fenêtre de dialogue.</target>
</trans-unit>
<trans-unit id="{1} is loading.">
<source>{1} is loading.</source>
<target>{1} est en train de charger</target>
</trans-unit>
<trans-unit id="Quality">
<source>Quality</source>
<target>Qualité</target>
</trans-unit>
<trans-unit id="Auto">
<source>Auto</source>
<target>Auto</target>
</trans-unit>
<trans-unit id="Speed">
<source>Speed</source>
<target>Vitesse</target>
</trans-unit>
<trans-unit id="peers">
<source>peers</source>
<target>pairs</target>
</trans-unit>
<trans-unit id="Go to the video page">
<source>Go to the video page</source>
<target>Aller sur la page de la vidéo</target>
</trans-unit>
<trans-unit id="Settings">
<source>Settings</source>
<target>Paramètres</target>
</trans-unit>
<trans-unit id="Uses P2P, others may know you are watching this video.">
<source>Uses P2P, others may know you are watching this video.</source>
<target>Utilise le P2P, d'autres personnes pourraient savoir que vous regardez cette vidéo.</target>
</trans-unit>
<trans-unit id="Copy the video URL">
<source>Copy the video URL</source>
<target>Copier le lien de la vidéo</target>
</trans-unit>
<trans-unit id="Copy the video URL at the current time">
<source>Copy the video URL at the current time</source>
<target>Copier le lien de la vidéo à partir de cette séquence</target>
</trans-unit>
<trans-unit id="Copy embed code">
<source>Copy embed code</source>
<target>Copier le code d'intégration</target>
</trans-unit>
</body>
</file></xliff>

View File

@ -0,0 +1 @@
{"Music":"Musique","Films":"Films","Vehicles":"Transport","Art":"Art","Sports":"Sports","Travels":"Voyages","Gaming":"Jeux vidéos","People":"People","Comedy":"Humour","Entertainment":"Divertissement","News":"Actualités","How To":"Tutoriel","Education":"Éducation","Activism":"Activisme","Science & Technology":"Science & Technologie","Animals":"Animaux","Kids":"Enfants","Food":"Cuisine","Attribution":"Attribution","Attribution - Share Alike":"Attribution - Partage dans les mêmes conditions","Attribution - No Derivatives":"Attribution - Pas d'oeuvre dérivée","Attribution - Non Commercial":"Attribution - Utilisation non commerciale","Attribution - Non Commercial - Share Alike":"Attribution - Utilisation non commerciale - Partage dans les mêmes conditions","Attribution - Non Commercial - No Derivatives":"Attribution - Utilisation non commerciale - Pas d'oeuvre dérivée","Public Domain Dedication":"Domaine public","Public":"Publique","Unlisted":"Non listée","Private":"Privée","French":"Français","French Sign Language":"Langage des signes français","Misc":"Divers","Unknown":"Inconnu"}

View File

@ -1,12 +1,15 @@
import * as jsToXliff12 from 'xliff/jsToXliff12' import * as jsToXliff12 from 'xliff/jsToXliff12'
import { writeFile } from 'fs' import { writeFile } from 'fs'
import { join } from 'path' import { join } from 'path'
import { buildLanguages, VIDEO_CATEGORIES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../server/initializers/constants'
import { values } from 'lodash'
// First, the player type TranslationType = {
const playerSource = join(__dirname, '../../../client/src/locale/source/videojs_en_US.json') target: string
const playerTarget = join(__dirname, '../../../client/src/locale/source/player_en_US.xml') data: { [id: string]: string }
}
const videojs = require(playerSource) const videojs = require(join(__dirname, '../../../client/src/locale/source/videojs_en_US.json'))
const playerKeys = { const playerKeys = {
'Quality': 'Quality', 'Quality': 'Quality',
'Auto': 'Auto', 'Auto': 'Auto',
@ -19,36 +22,65 @@ const playerKeys = {
'Copy the video URL at the current time': 'Copy the video URL at the current time', 'Copy the video URL at the current time': 'Copy the video URL at the current time',
'Copy embed code': 'Copy embed code' 'Copy embed code': 'Copy embed code'
} }
const playerTranslations = {
const obj = { target: join(__dirname, '../../../client/src/locale/source/player_en_US.xml'),
resources: { data: Object.assign({}, videojs, playerKeys)
namespace1: {}
}
} }
for (const sourceObject of [ videojs, playerKeys ]) { // Server keys
Object.keys(sourceObject).forEach(k => obj.resources.namespace1[ k ] = { source: sourceObject[ k ] }) const serverKeys: any = {}
values(VIDEO_CATEGORIES)
.concat(values(VIDEO_LICENCES))
.concat(values(VIDEO_PRIVACIES))
.forEach(v => serverKeys[v] = v)
// ISO 639 keys
const languages = buildLanguages()
Object.keys(languages).forEach(k => serverKeys[languages[k]] = languages[k])
// More keys
Object.assign(serverKeys, {
'Misc': 'Misc',
'Unknown': 'Unknown'
})
const serverTranslations = {
target: join(__dirname, '../../../client/src/locale/source/server_en_US.xml'),
data: serverKeys
} }
saveToXliffFile(playerTarget, obj, err => { saveToXliffFile(playerTranslations, err => {
if (err) { if (err) return handleError(err)
console.error(err)
process.exit(-1)
}
process.exit(0) saveToXliffFile(serverTranslations, err => {
if (err) return handleError(err)
process.exit(0)
})
}) })
// Then, the server strings // Then, the server strings
function saveToXliffFile (targetPath: string, obj: any, cb: Function) { function saveToXliffFile (jsonTranslations: TranslationType, cb: Function) {
const obj = {
resources: {
namespace1: {}
}
}
Object.keys(jsonTranslations.data).forEach(k => obj.resources.namespace1[ k ] = { source: jsonTranslations.data[ k ] })
jsToXliff12(obj, (err, res) => { jsToXliff12(obj, (err, res) => {
if (err) return cb(err) if (err) return cb(err)
writeFile(playerTarget, res, err => { writeFile(jsonTranslations.target, res, err => {
if (err) return cb(err) if (err) return cb(err)
return cb(null) return cb(null)
}) })
}) })
} }
function handleError (err: any) {
console.error(err)
process.exit(-1)
}

View File

@ -1,33 +1,53 @@
import * as xliff12ToJs from 'xliff/xliff12ToJs' import * as xliff12ToJs from 'xliff/xliff12ToJs'
import { readFileSync, writeFile } from 'fs' import { unlink, readFileSync, writeFile } from 'fs'
import { join } from 'path' import { join } from 'path'
import { buildFileLocale, I18N_LOCALES, isDefaultLocale } from '../../shared/models/i18n/i18n'
import { eachSeries } from 'async'
// First, the player const sources: string[] = []
const playerSource = join(__dirname, '../../../client/src/locale/target/player_fr.xml') const availableLocales = Object.keys(I18N_LOCALES)
const playerTarget = join(__dirname, '../../../client/src/locale/target/player_fr.json') .filter(l => isDefaultLocale(l) === false)
.map(l => buildFileLocale(l))
// Remove the two first lines our xliff module does not like for (const file of [ 'server', 'player' ]) {
let playerFile = readFileSync(playerSource).toString() for (const locale of availableLocales) {
playerFile = removeFirstLine(playerFile) sources.push(join(__dirname, '../../../client/src/locale/target/', `${file}_${locale}.xml`))
playerFile = removeFirstLine(playerFile)
xliff12ToJs(playerFile, (err, res) => {
if (err) {
console.error(err)
process.exit(-1)
} }
}
const json = createJSONString(res) eachSeries(sources, (source, cb) => {
writeFile(playerTarget, json, err => { xliffFile2JSON(source, cb)
if (err) { }, err => {
console.error(err) if (err) return handleError(err)
process.exit(-1)
}
process.exit(0) process.exit(0)
})
}) })
function handleError (err: any) {
console.error(err)
process.exit(-1)
}
function xliffFile2JSON (filePath: string, cb) {
const fileTarget = filePath.replace('.xml', '.json')
// Remove the two first lines our xliff module does not like
let fileContent = readFileSync(filePath).toString()
fileContent = removeFirstLine(fileContent)
fileContent = removeFirstLine(fileContent)
xliff12ToJs(fileContent, (err, res) => {
if (err) return cb(err)
const json = createJSONString(res)
writeFile(fileTarget, json, err => {
if (err) return cb(err)
return unlink(filePath, cb)
})
})
}
function removeFirstLine (str: string) { function removeFirstLine (str: string) {
return str.substring(str.indexOf('\n') + 1) return str.substring(str.indexOf('\n') + 1)
} }

View File

@ -48,8 +48,11 @@ clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE }
clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE })) clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE }))
clientsRouter.use('/client/locales/:locale/:file.json', function (req, res) { clientsRouter.use('/client/locales/:locale/:file.json', function (req, res) {
if (req.params.locale === 'fr' && req.params.file === 'player') { const locale = req.params.locale
return res.sendFile(join(__dirname, '../../../client/dist/locale/player_fr.json')) const file = req.params.file
if (is18nLocale(locale) && [ 'player', 'server' ].indexOf(file) !== -1) {
return res.sendFile(join(__dirname, `../../../client/dist/locale/${file}_${locale}.json`))
} }
return res.sendStatus(404) return res.sendStatus(404)

View File

@ -500,7 +500,8 @@ export {
STATIC_DOWNLOAD_PATHS, STATIC_DOWNLOAD_PATHS,
RATES_LIMIT, RATES_LIMIT,
JOB_COMPLETED_LIFETIME, JOB_COMPLETED_LIFETIME,
VIDEO_VIEW_LIFETIME VIDEO_VIEW_LIFETIME,
buildLanguages
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------