diff options
author | Chocobozzz <me@florianbigard.com> | 2018-06-06 14:23:40 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-06-06 16:48:40 +0200 |
commit | e945b184a0f29b47c33bbd05578f3493ca9c8e6c (patch) | |
tree | 46c821006d170e6e28658d978e313761adfaf55a | |
parent | 550a562ceca45ea78d6f7054024c8d3a6b89c30c (diff) | |
download | PeerTube-e945b184a0f29b47c33bbd05578f3493ca9c8e6c.tar.gz PeerTube-e945b184a0f29b47c33bbd05578f3493ca9c8e6c.tar.zst PeerTube-e945b184a0f29b47c33bbd05578f3493ca9c8e6c.zip |
Localize player
23 files changed, 1049 insertions, 61 deletions
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 23d74494c..d3e16c4cf 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { catchError } from 'rxjs/operators' | 1 | import { catchError } from 'rxjs/operators' |
2 | import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' | 2 | import { Component, ElementRef, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild, Inject } from '@angular/core' |
3 | import { ActivatedRoute, Router } from '@angular/router' | 3 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { RedirectService } from '@app/core/routing/redirect.service' | 4 | import { RedirectService } from '@app/core/routing/redirect.service' |
5 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | 5 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' |
@@ -21,9 +21,10 @@ import { MarkdownService } from '../shared' | |||
21 | import { VideoDownloadComponent } from './modal/video-download.component' | 21 | import { VideoDownloadComponent } from './modal/video-download.component' |
22 | import { VideoReportComponent } from './modal/video-report.component' | 22 | import { VideoReportComponent } from './modal/video-report.component' |
23 | import { VideoShareComponent } from './modal/video-share.component' | 23 | import { VideoShareComponent } from './modal/video-share.component' |
24 | import { getVideojsOptions } from '../../../assets/player/peertube-player' | 24 | import { getVideojsOptions, loadLocale, addContextMenu } from '../../../assets/player/peertube-player' |
25 | import { ServerService } from '@app/core' | 25 | import { ServerService } from '@app/core' |
26 | import { I18n } from '@ngx-translate/i18n-polyfill' | 26 | import { I18n } from '@ngx-translate/i18n-polyfill' |
27 | import { environment } from '../../../environments/environment' | ||
27 | 28 | ||
28 | @Component({ | 29 | @Component({ |
29 | selector: 'my-video-watch', | 30 | selector: 'my-video-watch', |
@@ -54,6 +55,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
54 | likesBarTooltipText = '' | 55 | likesBarTooltipText = '' |
55 | hasAlreadyAcceptedPrivacyConcern = false | 56 | hasAlreadyAcceptedPrivacyConcern = false |
56 | 57 | ||
58 | private videojsLocaleLoaded = false | ||
57 | private otherVideos: Video[] = [] | 59 | private otherVideos: Video[] = [] |
58 | private paramsSub: Subscription | 60 | private paramsSub: Subscription |
59 | 61 | ||
@@ -72,7 +74,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
72 | private markdownService: MarkdownService, | 74 | private markdownService: MarkdownService, |
73 | private zone: NgZone, | 75 | private zone: NgZone, |
74 | private redirectService: RedirectService, | 76 | private redirectService: RedirectService, |
75 | private i18n: I18n | 77 | private i18n: I18n, |
78 | @Inject(LOCALE_ID) private localeId: string | ||
76 | ) {} | 79 | ) {} |
77 | 80 | ||
78 | get user () { | 81 | get user () { |
@@ -365,7 +368,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
365 | inactivityTimeout: 2500, | 368 | inactivityTimeout: 2500, |
366 | videoFiles: this.video.files, | 369 | videoFiles: this.video.files, |
367 | playerElement: this.playerElement, | 370 | playerElement: this.playerElement, |
368 | videoEmbedUrl: this.video.embedUrl, | ||
369 | videoViewUrl: this.videoService.getVideoViewUrl(this.video.uuid), | 371 | videoViewUrl: this.videoService.getVideoViewUrl(this.video.uuid), |
370 | videoDuration: this.video.duration, | 372 | videoDuration: this.video.duration, |
371 | enableHotkeys: true, | 373 | enableHotkeys: true, |
@@ -374,11 +376,18 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
374 | startTime | 376 | startTime |
375 | }) | 377 | }) |
376 | 378 | ||
379 | if (this.videojsLocaleLoaded === false) { | ||
380 | await loadLocale(environment.apiUrl, videojs, environment.production === true ? this.localeId : 'fr') | ||
381 | this.videojsLocaleLoaded = true | ||
382 | } | ||
383 | |||
377 | const self = this | 384 | const self = this |
378 | this.zone.runOutsideAngular(() => { | 385 | this.zone.runOutsideAngular(async () => { |
379 | videojs(this.playerElement, videojsOptions, function () { | 386 | videojs(this.playerElement, videojsOptions, function () { |
380 | self.player = this | 387 | self.player = this |
381 | this.on('customError', (event, data) => self.handleError(data.err)) | 388 | this.on('customError', (event, data) => self.handleError(data.err)) |
389 | |||
390 | addContextMenu(self.player, self.video.embedUrl) | ||
382 | }) | 391 | }) |
383 | }) | 392 | }) |
384 | 393 | ||
diff --git a/client/src/assets/player/peertube-link-button.ts b/client/src/assets/player/peertube-link-button.ts index a13815d61..26f8b9d73 100644 --- a/client/src/assets/player/peertube-link-button.ts +++ b/client/src/assets/player/peertube-link-button.ts | |||
@@ -24,7 +24,7 @@ class PeerTubeLinkButton extends Button { | |||
24 | const el = videojsUntyped.dom.createEl('a', { | 24 | const el = videojsUntyped.dom.createEl('a', { |
25 | href: buildVideoLink(), | 25 | href: buildVideoLink(), |
26 | innerHTML: 'PeerTube', | 26 | innerHTML: 'PeerTube', |
27 | title: 'Go to the video page', | 27 | title: this.player_.localize('Go to the video page'), |
28 | className: 'vjs-peertube-link', | 28 | className: 'vjs-peertube-link', |
29 | target: '_blank' | 29 | target: '_blank' |
30 | }) | 30 | }) |
diff --git a/client/src/assets/player/peertube-player.ts b/client/src/assets/player/peertube-player.ts index d204b9703..b604097fa 100644 --- a/client/src/assets/player/peertube-player.ts +++ b/client/src/assets/player/peertube-player.ts | |||
@@ -12,6 +12,7 @@ import './peertube-videojs-plugin' | |||
12 | import './peertube-load-progress-bar' | 12 | import './peertube-load-progress-bar' |
13 | import { videojsUntyped } from './peertube-videojs-typings' | 13 | import { videojsUntyped } from './peertube-videojs-typings' |
14 | import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' | 14 | import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' |
15 | import { is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' | ||
15 | 16 | ||
16 | // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) | 17 | // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) |
17 | videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed' | 18 | videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed' |
@@ -20,7 +21,6 @@ function getVideojsOptions (options: { | |||
20 | autoplay: boolean, | 21 | autoplay: boolean, |
21 | playerElement: HTMLVideoElement, | 22 | playerElement: HTMLVideoElement, |
22 | videoViewUrl: string, | 23 | videoViewUrl: string, |
23 | videoEmbedUrl: string, | ||
24 | videoDuration: number, | 24 | videoDuration: number, |
25 | videoFiles: VideoFile[], | 25 | videoFiles: VideoFile[], |
26 | enableHotkeys: boolean, | 26 | enableHotkeys: boolean, |
@@ -43,29 +43,6 @@ function getVideojsOptions (options: { | |||
43 | videoViewUrl: options.videoViewUrl, | 43 | videoViewUrl: options.videoViewUrl, |
44 | videoDuration: options.videoDuration, | 44 | videoDuration: options.videoDuration, |
45 | startTime: options.startTime | 45 | startTime: options.startTime |
46 | }, | ||
47 | contextmenuUI: { | ||
48 | content: [ | ||
49 | { | ||
50 | label: 'Copy the video URL', | ||
51 | listener: function () { | ||
52 | copyToClipboard(buildVideoLink()) | ||
53 | } | ||
54 | }, | ||
55 | { | ||
56 | label: 'Copy the video URL at the current time', | ||
57 | listener: function () { | ||
58 | const player = this | ||
59 | copyToClipboard(buildVideoLink(player.currentTime())) | ||
60 | } | ||
61 | }, | ||
62 | { | ||
63 | label: 'Copy embed code', | ||
64 | listener: () => { | ||
65 | copyToClipboard(buildVideoEmbed(options.videoEmbedUrl)) | ||
66 | } | ||
67 | } | ||
68 | ] | ||
69 | } | 46 | } |
70 | }, | 47 | }, |
71 | controlBar: { | 48 | controlBar: { |
@@ -135,4 +112,44 @@ function getControlBarChildren (options: { | |||
135 | return children | 112 | return children |
136 | } | 113 | } |
137 | 114 | ||
138 | export { getVideojsOptions } | 115 | function addContextMenu (player: any, videoEmbedUrl: string) { |
116 | console.log(videoEmbedUrl) | ||
117 | |||
118 | player.contextmenuUI({ | ||
119 | content: [ | ||
120 | { | ||
121 | label: player.localize('Copy the video URL'), | ||
122 | listener: function () { | ||
123 | copyToClipboard(buildVideoLink()) | ||
124 | } | ||
125 | }, | ||
126 | { | ||
127 | label: player.localize('Copy the video URL at the current time'), | ||
128 | listener: function () { | ||
129 | const player = this | ||
130 | copyToClipboard(buildVideoLink(player.currentTime())) | ||
131 | } | ||
132 | }, | ||
133 | { | ||
134 | label: player.localize('Copy embed code'), | ||
135 | listener: () => { | ||
136 | copyToClipboard(buildVideoEmbed(videoEmbedUrl)) | ||
137 | } | ||
138 | } | ||
139 | ] | ||
140 | }) | ||
141 | } | ||
142 | |||
143 | function loadLocale (serverUrl: string, videojs: any, locale: string) { | ||
144 | if (!is18nLocale(locale) || isDefaultLocale(locale)) return undefined | ||
145 | |||
146 | return fetch(serverUrl + '/client/locales/' + locale + '/player.json') | ||
147 | .then(res => res.json()) | ||
148 | .then(json => videojs.addLanguage(locale, json)) | ||
149 | } | ||
150 | |||
151 | export { | ||
152 | loadLocale, | ||
153 | getVideojsOptions, | ||
154 | addContextMenu | ||
155 | } | ||
diff --git a/client/src/assets/player/peertube-videojs-plugin.ts b/client/src/assets/player/peertube-videojs-plugin.ts index 79df42a53..68e98f170 100644 --- a/client/src/assets/player/peertube-videojs-plugin.ts +++ b/client/src/assets/player/peertube-videojs-plugin.ts | |||
@@ -4,15 +4,7 @@ import { VideoFile } from '../../../../shared/models/videos/video.model' | |||
4 | import { renderVideo } from './video-renderer' | 4 | import { renderVideo } from './video-renderer' |
5 | import './settings-menu-button' | 5 | import './settings-menu-button' |
6 | import { PeertubePluginOptions, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' | 6 | import { PeertubePluginOptions, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' |
7 | import { | 7 | import { getAverageBandwidth, getStoredMute, getStoredVolume, saveAverageBandwidth, saveMuteInStore, saveVolumeInStore } from './utils' |
8 | getAverageBandwidth, | ||
9 | getStoredMute, | ||
10 | getStoredVolume, | ||
11 | isMobile, | ||
12 | saveAverageBandwidth, | ||
13 | saveMuteInStore, | ||
14 | saveVolumeInStore | ||
15 | } from './utils' | ||
16 | import minBy from 'lodash-es/minBy' | 8 | import minBy from 'lodash-es/minBy' |
17 | import maxBy from 'lodash-es/maxBy' | 9 | import maxBy from 'lodash-es/maxBy' |
18 | import * as CacheChunkStore from 'cache-chunk-store' | 10 | import * as CacheChunkStore from 'cache-chunk-store' |
diff --git a/client/src/assets/player/resolution-menu-button.ts b/client/src/assets/player/resolution-menu-button.ts index 2efc8de69..d317a5efc 100644 --- a/client/src/assets/player/resolution-menu-button.ts +++ b/client/src/assets/player/resolution-menu-button.ts | |||
@@ -8,10 +8,7 @@ class ResolutionMenuButton extends MenuButton { | |||
8 | label: HTMLElement | 8 | label: HTMLElement |
9 | 9 | ||
10 | constructor (player: videojs.Player, options) { | 10 | constructor (player: videojs.Player, options) { |
11 | options.label = 'Quality' | ||
12 | super(player, options) | 11 | super(player, options) |
13 | |||
14 | this.controlText_ = 'Quality' | ||
15 | this.player = player | 12 | this.player = player |
16 | 13 | ||
17 | player.peertube().on('videoFileUpdate', () => this.updateLabel()) | 14 | player.peertube().on('videoFileUpdate', () => this.updateLabel()) |
@@ -51,7 +48,7 @@ class ResolutionMenuButton extends MenuButton { | |||
51 | this.player_, | 48 | this.player_, |
52 | { | 49 | { |
53 | id: -1, | 50 | id: -1, |
54 | label: 'Auto', | 51 | label: this.player_.localize('Auto'), |
55 | src: null | 52 | src: null |
56 | } | 53 | } |
57 | )) | 54 | )) |
@@ -77,4 +74,6 @@ class ResolutionMenuButton extends MenuButton { | |||
77 | return this.player_.peertube().getCurrentResolutionLabel() | 74 | return this.player_.peertube().getCurrentResolutionLabel() |
78 | } | 75 | } |
79 | } | 76 | } |
77 | ResolutionMenuButton.prototype.controlText_ = 'Quality' | ||
78 | |||
80 | MenuButton.registerComponent('ResolutionMenuButton', ResolutionMenuButton) | 79 | MenuButton.registerComponent('ResolutionMenuButton', ResolutionMenuButton) |
diff --git a/client/src/assets/player/settings-menu-button.ts b/client/src/assets/player/settings-menu-button.ts index bf6ac145a..b51c52506 100644 --- a/client/src/assets/player/settings-menu-button.ts +++ b/client/src/assets/player/settings-menu-button.ts | |||
@@ -275,7 +275,7 @@ class SettingsDialog extends Component { | |||
275 | 275 | ||
276 | } | 276 | } |
277 | 277 | ||
278 | SettingsButton.prototype.controlText_ = 'Settings Button' | 278 | SettingsButton.prototype.controlText_ = 'Settings' |
279 | 279 | ||
280 | Component.registerComponent('SettingsButton', SettingsButton) | 280 | Component.registerComponent('SettingsButton', SettingsButton) |
281 | Component.registerComponent('SettingsDialog', SettingsDialog) | 281 | Component.registerComponent('SettingsDialog', SettingsDialog) |
diff --git a/client/src/assets/player/settings-menu-item.ts b/client/src/assets/player/settings-menu-item.ts index 048c88533..f595fd459 100644 --- a/client/src/assets/player/settings-menu-item.ts +++ b/client/src/assets/player/settings-menu-item.ts | |||
@@ -132,7 +132,7 @@ class SettingsMenuItem extends MenuItem { | |||
132 | const button = this.subMenu.menu.addChild('MenuItem', {}, 0) | 132 | const button = this.subMenu.menu.addChild('MenuItem', {}, 0) |
133 | button.name_ = 'BackButton' | 133 | button.name_ = 'BackButton' |
134 | button.addClass('vjs-back-button') | 134 | button.addClass('vjs-back-button') |
135 | button.el_.innerHTML = this.subMenu.controlText_ | 135 | button.el_.innerHTML = this.player_.localize(this.subMenu.controlText_) |
136 | } | 136 | } |
137 | 137 | ||
138 | /** | 138 | /** |
@@ -201,7 +201,7 @@ class SettingsMenuItem extends MenuItem { | |||
201 | saveUpdateLabel.call(this.subMenu) | 201 | saveUpdateLabel.call(this.subMenu) |
202 | } | 202 | } |
203 | 203 | ||
204 | this.settingsSubMenuTitleEl_.innerHTML = this.subMenu.controlText_ | 204 | this.settingsSubMenuTitleEl_.innerHTML = this.player_.localize(this.subMenu.controlText_) |
205 | this.settingsSubMenuEl_.appendChild(this.subMenu.menu.el_) | 205 | this.settingsSubMenuEl_.appendChild(this.subMenu.menu.el_) |
206 | this.panelChildEl.appendChild(this.settingsSubMenuEl_) | 206 | this.panelChildEl.appendChild(this.settingsSubMenuEl_) |
207 | this.update() | 207 | this.update() |
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts index 487b3a1be..ce7aaea2a 100644 --- a/client/src/assets/player/utils.ts +++ b/client/src/assets/player/utils.ts | |||
@@ -1,3 +1,5 @@ | |||
1 | import { is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' | ||
2 | |||
1 | function toTitleCase (str: string) { | 3 | function toTitleCase (str: string) { |
2 | return str.charAt(0).toUpperCase() + str.slice(1) | 4 | return str.charAt(0).toUpperCase() + str.slice(1) |
3 | } | 5 | } |
diff --git a/client/src/assets/player/webtorrent-info-button.ts b/client/src/assets/player/webtorrent-info-button.ts index baeb22b64..10945c665 100644 --- a/client/src/assets/player/webtorrent-info-button.ts +++ b/client/src/assets/player/webtorrent-info-button.ts | |||
@@ -60,13 +60,8 @@ class WebtorrentInfoButton extends Button { | |||
60 | className: 'peers-number', | 60 | className: 'peers-number', |
61 | textContent: 'HTTP' | 61 | textContent: 'HTTP' |
62 | }) | 62 | }) |
63 | const subDivFallbackText = videojsUntyped.dom.createEl('span', { | ||
64 | className: 'peers-text', | ||
65 | textContent: ' fallback' | ||
66 | }) | ||
67 | 63 | ||
68 | subDivHttp.appendChild(subDivHttpText) | 64 | subDivHttp.appendChild(subDivHttpText) |
69 | subDivHttp.appendChild(subDivFallbackText) | ||
70 | div.appendChild(subDivHttp) | 65 | div.appendChild(subDivHttp) |
71 | 66 | ||
72 | this.player_.peertube().on('torrentInfo', (event, data) => { | 67 | this.player_.peertube().on('torrentInfo', (event, data) => { |
@@ -89,7 +84,7 @@ class WebtorrentInfoButton extends Button { | |||
89 | uploadSpeedUnit.textContent = ' ' + uploadSpeed[ 1 ] | 84 | uploadSpeedUnit.textContent = ' ' + uploadSpeed[ 1 ] |
90 | 85 | ||
91 | peersNumber.textContent = numPeers | 86 | peersNumber.textContent = numPeers |
92 | peersText.textContent = ' peers' | 87 | peersText.textContent = ' ' + this.player_.localize('peers') |
93 | 88 | ||
94 | subDivHttp.className = 'vjs-peertube-hidden' | 89 | subDivHttp.className = 'vjs-peertube-hidden' |
95 | subDivWebtorrent.className = 'vjs-peertube-displayed' | 90 | subDivWebtorrent.className = 'vjs-peertube-displayed' |
diff --git a/client/src/locale/source/player_en_US.xml b/client/src/locale/source/player_en_US.xml new file mode 100644 index 000000000..5bb6afdf7 --- /dev/null +++ b/client/src/locale/source/player_en_US.xml | |||
@@ -0,0 +1,378 @@ | |||
1 | <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"> | ||
2 | <file original="namespace1" datatype="plaintext" source-language="undefined" target-language="undefined"> | ||
3 | <body> | ||
4 | <trans-unit id="Audio Player"> | ||
5 | <source>Audio Player</source> | ||
6 | <target>undefined</target> | ||
7 | </trans-unit> | ||
8 | <trans-unit id="Video Player"> | ||
9 | <source>Video Player</source> | ||
10 | <target>undefined</target> | ||
11 | </trans-unit> | ||
12 | <trans-unit id="Play"> | ||
13 | <source>Play</source> | ||
14 | <target>undefined</target> | ||
15 | </trans-unit> | ||
16 | <trans-unit id="Pause"> | ||
17 | <source>Pause</source> | ||
18 | <target>undefined</target> | ||
19 | </trans-unit> | ||
20 | <trans-unit id="Replay"> | ||
21 | <source>Replay</source> | ||
22 | <target>undefined</target> | ||
23 | </trans-unit> | ||
24 | <trans-unit id="Current Time"> | ||
25 | <source>Current Time</source> | ||
26 | <target>undefined</target> | ||
27 | </trans-unit> | ||
28 | <trans-unit id="Duration"> | ||
29 | <source>Duration</source> | ||
30 | <target>undefined</target> | ||
31 | </trans-unit> | ||
32 | <trans-unit id="Remaining Time"> | ||
33 | <source>Remaining Time</source> | ||
34 | <target>undefined</target> | ||
35 | </trans-unit> | ||
36 | <trans-unit id="Stream Type"> | ||
37 | <source>Stream Type</source> | ||
38 | <target>undefined</target> | ||
39 | </trans-unit> | ||
40 | <trans-unit id="LIVE"> | ||
41 | <source>LIVE</source> | ||
42 | <target>undefined</target> | ||
43 | </trans-unit> | ||
44 | <trans-unit id="Loaded"> | ||
45 | <source>Loaded</source> | ||
46 | <target>undefined</target> | ||
47 | </trans-unit> | ||
48 | <trans-unit id="Progress"> | ||
49 | <source>Progress</source> | ||
50 | <target>undefined</target> | ||
51 | </trans-unit> | ||
52 | <trans-unit id="Progress Bar"> | ||
53 | <source>Progress Bar</source> | ||
54 | <target>undefined</target> | ||
55 | </trans-unit> | ||
56 | <trans-unit id="progress bar timing: currentTime={1} duration={2}"> | ||
57 | <source>{1} of {2}</source> | ||
58 | <target>undefined</target> | ||
59 | </trans-unit> | ||
60 | <trans-unit id="Fullscreen"> | ||
61 | <source>Fullscreen</source> | ||
62 | <target>undefined</target> | ||
63 | </trans-unit> | ||
64 | <trans-unit id="Non-Fullscreen"> | ||
65 | <source>Non-Fullscreen</source> | ||
66 | <target>undefined</target> | ||
67 | </trans-unit> | ||
68 | <trans-unit id="Mute"> | ||
69 | <source>Mute</source> | ||
70 | <target>undefined</target> | ||
71 | </trans-unit> | ||
72 | <trans-unit id="Unmute"> | ||
73 | <source>Unmute</source> | ||
74 | <target>undefined</target> | ||
75 | </trans-unit> | ||
76 | <trans-unit id="Playback Rate"> | ||
77 | <source>Playback Rate</source> | ||
78 | <target>undefined</target> | ||
79 | </trans-unit> | ||
80 | <trans-unit id="Subtitles"> | ||
81 | <source>Subtitles</source> | ||
82 | <target>undefined</target> | ||
83 | </trans-unit> | ||
84 | <trans-unit id="subtitles off"> | ||
85 | <source>subtitles off</source> | ||
86 | <target>undefined</target> | ||
87 | </trans-unit> | ||
88 | <trans-unit id="Captions"> | ||
89 | <source>Captions</source> | ||
90 | <target>undefined</target> | ||
91 | </trans-unit> | ||
92 | <trans-unit id="captions off"> | ||
93 | <source>captions off</source> | ||
94 | <target>undefined</target> | ||
95 | </trans-unit> | ||
96 | <trans-unit id="Chapters"> | ||
97 | <source>Chapters</source> | ||
98 | <target>undefined</target> | ||
99 | </trans-unit> | ||
100 | <trans-unit id="Descriptions"> | ||
101 | <source>Descriptions</source> | ||
102 | <target>undefined</target> | ||
103 | </trans-unit> | ||
104 | <trans-unit id="descriptions off"> | ||
105 | <source>descriptions off</source> | ||
106 | <target>undefined</target> | ||
107 | </trans-unit> | ||
108 | <trans-unit id="Audio Track"> | ||
109 | <source>Audio Track</source> | ||
110 | <target>undefined</target> | ||
111 | </trans-unit> | ||
112 | <trans-unit id="Volume Level"> | ||
113 | <source>Volume Level</source> | ||
114 | <target>undefined</target> | ||
115 | </trans-unit> | ||
116 | <trans-unit id="You aborted the media playback"> | ||
117 | <source>You aborted the media playback</source> | ||
118 | <target>undefined</target> | ||
119 | </trans-unit> | ||
120 | <trans-unit id="A network error caused the media download to fail part-way."> | ||
121 | <source>A network error caused the media download to fail part-way.</source> | ||
122 | <target>undefined</target> | ||
123 | </trans-unit> | ||
124 | <trans-unit id="The media could not be loaded, either because the server or network failed or because the format is not supported."> | ||
125 | <source>The media could not be loaded, either because the server or network failed or because the format is not supported.</source> | ||
126 | <target>undefined</target> | ||
127 | </trans-unit> | ||
128 | <trans-unit id="The media playback was aborted due to a corruption problem or because the media used features your browser did not support."> | ||
129 | <source>The media playback was aborted due to a corruption problem or because the media used features your browser did not support.</source> | ||
130 | <target>undefined</target> | ||
131 | </trans-unit> | ||
132 | <trans-unit id="No compatible source was found for this media."> | ||
133 | <source>No compatible source was found for this media.</source> | ||
134 | <target>undefined</target> | ||
135 | </trans-unit> | ||
136 | <trans-unit id="The media is encrypted and we do not have the keys to decrypt it."> | ||
137 | <source>The media is encrypted and we do not have the keys to decrypt it.</source> | ||
138 | <target>undefined</target> | ||
139 | </trans-unit> | ||
140 | <trans-unit id="Play Video"> | ||
141 | <source>Play Video</source> | ||
142 | <target>undefined</target> | ||
143 | </trans-unit> | ||
144 | <trans-unit id="Close"> | ||
145 | <source>Close</source> | ||
146 | <target>undefined</target> | ||
147 | </trans-unit> | ||
148 | <trans-unit id="Close Modal Dialog"> | ||
149 | <source>Close Modal Dialog</source> | ||
150 | <target>undefined</target> | ||
151 | </trans-unit> | ||
152 | <trans-unit id="Modal Window"> | ||
153 | <source>Modal Window</source> | ||
154 | <target>undefined</target> | ||
155 | </trans-unit> | ||
156 | <trans-unit id="This is a modal window"> | ||
157 | <source>This is a modal window</source> | ||
158 | <target>undefined</target> | ||
159 | </trans-unit> | ||
160 | <trans-unit id="This modal can be closed by pressing the Escape key or activating the close button."> | ||
161 | <source>This modal can be closed by pressing the Escape key or activating the close button.</source> | ||
162 | <target>undefined</target> | ||
163 | </trans-unit> | ||
164 | <trans-unit id=", opens captions settings dialog"> | ||
165 | <source>, opens captions settings dialog</source> | ||
166 | <target>undefined</target> | ||
167 | </trans-unit> | ||
168 | <trans-unit id=", opens subtitles settings dialog"> | ||
169 | <source>, opens subtitles settings dialog</source> | ||
170 | <target>undefined</target> | ||
171 | </trans-unit> | ||
172 | <trans-unit id=", opens descriptions settings dialog"> | ||
173 | <source>, opens descriptions settings dialog</source> | ||
174 | <target>undefined</target> | ||
175 | </trans-unit> | ||
176 | <trans-unit id=", selected"> | ||
177 | <source>, selected</source> | ||
178 | <target>undefined</target> | ||
179 | </trans-unit> | ||
180 | <trans-unit id="captions settings"> | ||
181 | <source>captions settings</source> | ||
182 | <target>undefined</target> | ||
183 | </trans-unit> | ||
184 | <trans-unit id="subtitles settings"> | ||
185 | <source>subititles settings</source> | ||
186 | <target>undefined</target> | ||
187 | </trans-unit> | ||
188 | <trans-unit id="descriptions settings"> | ||
189 | <source>descriptions settings</source> | ||
190 | <target>undefined</target> | ||
191 | </trans-unit> | ||
192 | <trans-unit id="Text"> | ||
193 | <source>Text</source> | ||
194 | <target>undefined</target> | ||
195 | </trans-unit> | ||
196 | <trans-unit id="White"> | ||
197 | <source>White</source> | ||
198 | <target>undefined</target> | ||
199 | </trans-unit> | ||
200 | <trans-unit id="Black"> | ||
201 | <source>Black</source> | ||
202 | <target>undefined</target> | ||
203 | </trans-unit> | ||
204 | <trans-unit id="Red"> | ||
205 | <source>Red</source> | ||
206 | <target>undefined</target> | ||
207 | </trans-unit> | ||
208 | <trans-unit id="Green"> | ||
209 | <source>Green</source> | ||
210 | <target>undefined</target> | ||
211 | </trans-unit> | ||
212 | <trans-unit id="Blue"> | ||
213 | <source>Blue</source> | ||
214 | <target>undefined</target> | ||
215 | </trans-unit> | ||
216 | <trans-unit id="Yellow"> | ||
217 | <source>Yellow</source> | ||
218 | <target>undefined</target> | ||
219 | </trans-unit> | ||
220 | <trans-unit id="Magenta"> | ||
221 | <source>Magenta</source> | ||
222 | <target>undefined</target> | ||
223 | </trans-unit> | ||
224 | <trans-unit id="Cyan"> | ||
225 | <source>Cyan</source> | ||
226 | <target>undefined</target> | ||
227 | </trans-unit> | ||
228 | <trans-unit id="Background"> | ||
229 | <source>Background</source> | ||
230 | <target>undefined</target> | ||
231 | </trans-unit> | ||
232 | <trans-unit id="Window"> | ||
233 | <source>Window</source> | ||
234 | <target>undefined</target> | ||
235 | </trans-unit> | ||
236 | <trans-unit id="Transparent"> | ||
237 | <source>Transparent</source> | ||
238 | <target>undefined</target> | ||
239 | </trans-unit> | ||
240 | <trans-unit id="Semi-Transparent"> | ||
241 | <source>Semi-Transparent</source> | ||
242 | <target>undefined</target> | ||
243 | </trans-unit> | ||
244 | <trans-unit id="Opaque"> | ||
245 | <source>Opaque</source> | ||
246 | <target>undefined</target> | ||
247 | </trans-unit> | ||
248 | <trans-unit id="Font Size"> | ||
249 | <source>Font Size</source> | ||
250 | <target>undefined</target> | ||
251 | </trans-unit> | ||
252 | <trans-unit id="Text Edge Style"> | ||
253 | <source>Text Edge Style</source> | ||
254 | <target>undefined</target> | ||
255 | </trans-unit> | ||
256 | <trans-unit id="None"> | ||
257 | <source>None</source> | ||
258 | <target>undefined</target> | ||
259 | </trans-unit> | ||
260 | <trans-unit id="Raised"> | ||
261 | <source>Raised</source> | ||
262 | <target>undefined</target> | ||
263 | </trans-unit> | ||
264 | <trans-unit id="Depressed"> | ||
265 | <source>Depressed</source> | ||
266 | <target>undefined</target> | ||
267 | </trans-unit> | ||
268 | <trans-unit id="Uniform"> | ||
269 | <source>Uniform</source> | ||
270 | <target>undefined</target> | ||
271 | </trans-unit> | ||
272 | <trans-unit id="Dropshadow"> | ||
273 | <source>Dropshadow</source> | ||
274 | <target>undefined</target> | ||
275 | </trans-unit> | ||
276 | <trans-unit id="Font Family"> | ||
277 | <source>Font Family</source> | ||
278 | <target>undefined</target> | ||
279 | </trans-unit> | ||
280 | <trans-unit id="Proportional Sans-Serif"> | ||
281 | <source>Proportional Sans-Serif</source> | ||
282 | <target>undefined</target> | ||
283 | </trans-unit> | ||
284 | <trans-unit id="Monospace Sans-Serif"> | ||
285 | <source>Monospace Sans-Serif</source> | ||
286 | <target>undefined</target> | ||
287 | </trans-unit> | ||
288 | <trans-unit id="Proportional Serif"> | ||
289 | <source>Proportional Serif</source> | ||
290 | <target>undefined</target> | ||
291 | </trans-unit> | ||
292 | <trans-unit id="Monospace Serif"> | ||
293 | <source>Monospace Serif</source> | ||
294 | <target>undefined</target> | ||
295 | </trans-unit> | ||
296 | <trans-unit id="Casual"> | ||
297 | <source>Casual</source> | ||
298 | <target>undefined</target> | ||
299 | </trans-unit> | ||
300 | <trans-unit id="Script"> | ||
301 | <source>Script</source> | ||
302 | <target>undefined</target> | ||
303 | </trans-unit> | ||
304 | <trans-unit id="Small Caps"> | ||
305 | <source>Small Caps</source> | ||
306 | <target>undefined</target> | ||
307 | </trans-unit> | ||
308 | <trans-unit id="Reset"> | ||
309 | <source>Reset</source> | ||
310 | <target>undefined</target> | ||
311 | </trans-unit> | ||
312 | <trans-unit id="restore all settings to the default values"> | ||
313 | <source>restore all settings to the default values</source> | ||
314 | <target>undefined</target> | ||
315 | </trans-unit> | ||
316 | <trans-unit id="Done"> | ||
317 | <source>Done</source> | ||
318 | <target>undefined</target> | ||
319 | </trans-unit> | ||
320 | <trans-unit id="Caption Settings Dialog"> | ||
321 | <source>Caption Settings Dialog</source> | ||
322 | <target>undefined</target> | ||
323 | </trans-unit> | ||
324 | <trans-unit id="Beginning of dialog window. Escape will cancel and close the window."> | ||
325 | <source>Beginning of dialog window. Escape will cancel and close the window.</source> | ||
326 | <target>undefined</target> | ||
327 | </trans-unit> | ||
328 | <trans-unit id="End of dialog window."> | ||
329 | <source>End of dialog window.</source> | ||
330 | <target>undefined</target> | ||
331 | </trans-unit> | ||
332 | <trans-unit id="{1} is loading."> | ||
333 | <source>{1} is loading.</source> | ||
334 | <target>undefined</target> | ||
335 | </trans-unit> | ||
336 | <trans-unit id="Quality"> | ||
337 | <source>Quality</source> | ||
338 | <target>undefined</target> | ||
339 | </trans-unit> | ||
340 | <trans-unit id="Auto"> | ||
341 | <source>Auto</source> | ||
342 | <target>undefined</target> | ||
343 | </trans-unit> | ||
344 | <trans-unit id="Speed"> | ||
345 | <source>Speed</source> | ||
346 | <target>undefined</target> | ||
347 | </trans-unit> | ||
348 | <trans-unit id="peers"> | ||
349 | <source>peers</source> | ||
350 | <target>undefined</target> | ||
351 | </trans-unit> | ||
352 | <trans-unit id="Go to the video page"> | ||
353 | <source>Go to the video page</source> | ||
354 | <target>undefined</target> | ||
355 | </trans-unit> | ||
356 | <trans-unit id="Settings"> | ||
357 | <source>Settings</source> | ||
358 | <target>undefined</target> | ||
359 | </trans-unit> | ||
360 | <trans-unit id="Uses P2P, others may know you are watching this video."> | ||
361 | <source>Uses P2P, others may know you are watching this video.</source> | ||
362 | <target>undefined</target> | ||
363 | </trans-unit> | ||
364 | <trans-unit id="Copy the video URL"> | ||
365 | <source>Copy the video URL</source> | ||
366 | <target>undefined</target> | ||
367 | </trans-unit> | ||
368 | <trans-unit id="Copy the video URL at the current time"> | ||
369 | <source>Copy the video URL at the current time</source> | ||
370 | <target>undefined</target> | ||
371 | </trans-unit> | ||
372 | <trans-unit id="Copy embed code"> | ||
373 | <source>Copy embed code</source> | ||
374 | <target>undefined</target> | ||
375 | </trans-unit> | ||
376 | </body> | ||
377 | </file> | ||
378 | </xliff> \ No newline at end of file | ||
diff --git a/client/src/locale/source/videojs_en_US.json b/client/src/locale/source/videojs_en_US.json new file mode 100644 index 000000000..92caaa683 --- /dev/null +++ b/client/src/locale/source/videojs_en_US.json | |||
@@ -0,0 +1,85 @@ | |||
1 | { | ||
2 | "Audio Player": "Audio Player", | ||
3 | "Video Player": "Video Player", | ||
4 | "Play": "Play", | ||
5 | "Pause": "Pause", | ||
6 | "Replay": "Replay", | ||
7 | "Current Time": "Current Time", | ||
8 | "Duration": "Duration", | ||
9 | "Remaining Time": "Remaining Time", | ||
10 | "Stream Type": "Stream Type", | ||
11 | "LIVE": "LIVE", | ||
12 | "Loaded": "Loaded", | ||
13 | "Progress": "Progress", | ||
14 | "Progress Bar": "Progress Bar", | ||
15 | "progress bar timing: currentTime={1} duration={2}": "{1} of {2}", | ||
16 | "Fullscreen": "Fullscreen", | ||
17 | "Non-Fullscreen": "Non-Fullscreen", | ||
18 | "Mute": "Mute", | ||
19 | "Unmute": "Unmute", | ||
20 | "Playback Rate": "Playback Rate", | ||
21 | "Subtitles": "Subtitles", | ||
22 | "subtitles off": "subtitles off", | ||
23 | "Captions": "Captions", | ||
24 | "captions off": "captions off", | ||
25 | "Chapters": "Chapters", | ||
26 | "Descriptions": "Descriptions", | ||
27 | "descriptions off": "descriptions off", | ||
28 | "Audio Track": "Audio Track", | ||
29 | "Volume Level": "Volume Level", | ||
30 | "You aborted the media playback": "You aborted the media playback", | ||
31 | "A network error caused the media download to fail part-way.": "A network error caused the media download to fail part-way.", | ||
32 | "The media could not be loaded, either because the server or network failed or because the format is not supported.": "The media could not be loaded, either because the server or network failed or because the format is not supported.", | ||
33 | "The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "The media playback was aborted due to a corruption problem or because the media used features your browser did not support.", | ||
34 | "No compatible source was found for this media.": "No compatible source was found for this media.", | ||
35 | "The media is encrypted and we do not have the keys to decrypt it.": "The media is encrypted and we do not have the keys to decrypt it.", | ||
36 | "Play Video": "Play Video", | ||
37 | "Close": "Close", | ||
38 | "Close Modal Dialog": "Close Modal Dialog", | ||
39 | "Modal Window": "Modal Window", | ||
40 | "This is a modal window": "This is a modal window", | ||
41 | "This modal can be closed by pressing the Escape key or activating the close button.": "This modal can be closed by pressing the Escape key or activating the close button.", | ||
42 | ", opens captions settings dialog": ", opens captions settings dialog", | ||
43 | ", opens subtitles settings dialog": ", opens subtitles settings dialog", | ||
44 | ", opens descriptions settings dialog": ", opens descriptions settings dialog", | ||
45 | ", selected": ", selected", | ||
46 | "captions settings": "captions settings", | ||
47 | "subtitles settings": "subititles settings", | ||
48 | "descriptions settings": "descriptions settings", | ||
49 | "Text": "Text", | ||
50 | "White": "White", | ||
51 | "Black": "Black", | ||
52 | "Red": "Red", | ||
53 | "Green": "Green", | ||
54 | "Blue": "Blue", | ||
55 | "Yellow": "Yellow", | ||
56 | "Magenta": "Magenta", | ||
57 | "Cyan": "Cyan", | ||
58 | "Background": "Background", | ||
59 | "Window": "Window", | ||
60 | "Transparent": "Transparent", | ||
61 | "Semi-Transparent": "Semi-Transparent", | ||
62 | "Opaque": "Opaque", | ||
63 | "Font Size": "Font Size", | ||
64 | "Text Edge Style": "Text Edge Style", | ||
65 | "None": "None", | ||
66 | "Raised": "Raised", | ||
67 | "Depressed": "Depressed", | ||
68 | "Uniform": "Uniform", | ||
69 | "Dropshadow": "Dropshadow", | ||
70 | "Font Family": "Font Family", | ||
71 | "Proportional Sans-Serif": "Proportional Sans-Serif", | ||
72 | "Monospace Sans-Serif": "Monospace Sans-Serif", | ||
73 | "Proportional Serif": "Proportional Serif", | ||
74 | "Monospace Serif": "Monospace Serif", | ||
75 | "Casual": "Casual", | ||
76 | "Script": "Script", | ||
77 | "Small Caps": "Small Caps", | ||
78 | "Reset": "Reset", | ||
79 | "restore all settings to the default values": "restore all settings to the default values", | ||
80 | "Done": "Done", | ||
81 | "Caption Settings Dialog": "Caption Settings Dialog", | ||
82 | "Beginning of dialog window. Escape will cancel and close the window.": "Beginning of dialog window. Escape will cancel and close the window.", | ||
83 | "End of dialog window.": "End of dialog window.", | ||
84 | "{1} is loading.": "{1} is loading." | ||
85 | } | ||
diff --git a/client/src/locale/target/player_fr.json b/client/src/locale/target/player_fr.json new file mode 100644 index 000000000..6c399fc3f --- /dev/null +++ b/client/src/locale/target/player_fr.json | |||
@@ -0,0 +1 @@ | |||
{"Audio Player":"Lecteur audio","Video Player":"Lecteur vidéo","Play":"Lecture","Pause":"Pause","Replay":"Revoir","Current Time":"Temps actuel","Duration":"Durée","Remaining Time":"Temps restant","Stream Type":"Type de flux","LIVE":"EN DIRECT","Loaded":"Chargé","Progress":"Progression","Progress Bar":"Barre de progression","progress bar timing: currentTime={1} duration={2}":"{1} de {2}","Fullscreen":"Plein écran","Non-Fullscreen":"Fenêtré","Mute":"Sourdine","Unmute":"Son activé","Playback Rate":"Vitesse de lecture","Subtitles":"Sous-titres","subtitles off":"Sous-titres désactivés","Captions":"Sous-titres transcrits","captions off":"Sous-titres transcrits désactivés","Chapters":"Chapitres","Descriptions":"Descriptions","descriptions off":"descriptions désactivées","Audio Track":"Piste audio","Volume Level":"Niveau de volume","You aborted the media playback":"Vous avez interrompu la lecture de la vidéo.","A network error caused the media download to fail part-way.":"Une erreur de réseau a interrompu le téléchargement de la vidéo.","The media could not be loaded, either because the server or network failed or because the format is not supported.":"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.","The media playback was aborted due to a corruption problem or because the media used features your browser did not support.":"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.","No compatible source was found for this media.":"Aucune source compatible n'a été trouvée pour cette vidéo.","The media is encrypted and we do not have the keys to decrypt it.":"Le média est chiffré et nous n'avons pas les clés pour le déchiffrer.","Play Video":"Lire la vidéo","Close":"Fermer","Close Modal Dialog":"Fermer la boîte de dialogue modale","Modal Window":"Fenêtre modale","This is a modal window":"Ceci est une fenêtre modale","This modal can be closed by pressing the Escape key or activating the close button.":"Ce modal peut être fermé en appuyant sur la touche Échap ou activer le bouton de fermeture.",", opens captions settings dialog":", ouvrir les paramètres des sous-titres transcrits",", opens subtitles settings dialog":", ouvrir les paramètres des sous-titres",", opens descriptions settings dialog":", ouvrir les paramètres des descriptions",", selected":", sélectionné","captions settings":"Paramètres des sous-titres transcrits","subtitles settings":"Paramètres des sous-titres","descriptions settings":"Paramètres des descriptions","Text":"Texte","White":"Blanc","Black":"Noir","Red":"Rouge","Green":"Vert","Blue":"Bleu","Yellow":"Jaune","Magenta":"Magenta","Cyan":"Cyan","Background":"Arrière-plan","Window":"Fenêtre","Transparent":"Transparent","Semi-Transparent":"Semi-transparent","Opaque":"Opaque","Font Size":"Taille des caractères","Text Edge Style":"Style des contours du texte","None":"Aucun","Raised":"Élevé","Depressed":"Enfoncé","Uniform":"Uniforme","Dropshadow":"Ombre portée","Font Family":"Familles de polices","Proportional Sans-Serif":"Polices à chasse variable sans empattement (Proportional Sans-Serif)","Monospace Sans-Serif":"Polices à chasse fixe sans empattement (Monospace Sans-Serif)","Proportional Serif":"Polices à chasse variable avec empattement (Proportional Serif)","Monospace Serif":"Polices à chasse fixe avec empattement (Monospace Serif)","Casual":"Manuscrite","Script":"Scripte","Small Caps":"Petites capitales","Reset":"Réinitialiser","restore all settings to the default values":"Restaurer tous les paramètres aux valeurs par défaut","Done":"Terminé","Caption Settings Dialog":"Boîte de dialogue des paramètres des sous-titres transcrits","Beginning of dialog window. Escape will cancel and close the window.":"Début de la fenêtre de dialogue. La touche d'échappement annulera et fermera la fenêtre.","End of dialog window.":"Fin de la fenêtre de dialogue.","{1} is loading.":"{1} est en train de charger","Quality":"Qualité","Auto":"Auto","Speed":"Vitesse","peers":"pairs","Go to the video page":"Aller sur la page de la vidéo","Settings":"Paramètres","Uses P2P, others may know you are watching this video.":"Utilise le P2P, d'autres personnes pourraient savoir que vous regardez cette vidéo.","Copy the video URL":"Copier le lien de la vidéo","Copy the video URL at the current time":"Copier le lien de la vidéo à partir de cette séquence","Copy embed code":"Copier le code d'intégration"} \ No newline at end of file | |||
diff --git a/client/src/locale/target/player_fr.xml b/client/src/locale/target/player_fr.xml new file mode 100644 index 000000000..eafa4baff --- /dev/null +++ b/client/src/locale/target/player_fr.xml | |||
@@ -0,0 +1,379 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!--XLIFF document generated by Zanata. Visit http://zanata.org for more infomation.--> | ||
3 | <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"> | ||
4 | <file source-language="en-US" datatype="plaintext" original="" target-language="fr"> | ||
5 | <body> | ||
6 | <trans-unit id="Audio Player"> | ||
7 | <source>Audio Player</source> | ||
8 | <target>Lecteur audio</target> | ||
9 | </trans-unit> | ||
10 | <trans-unit id="Video Player"> | ||
11 | <source>Video Player</source> | ||
12 | <target>Lecteur vidéo</target> | ||
13 | </trans-unit> | ||
14 | <trans-unit id="Play"> | ||
15 | <source>Play</source> | ||
16 | <target>Lecture</target> | ||
17 | </trans-unit> | ||
18 | <trans-unit id="Pause"> | ||
19 | <source>Pause</source> | ||
20 | <target>Pause</target> | ||
21 | </trans-unit> | ||
22 | <trans-unit id="Replay"> | ||
23 | <source>Replay</source> | ||
24 | <target>Revoir</target> | ||
25 | </trans-unit> | ||
26 | <trans-unit id="Current Time"> | ||
27 | <source>Current Time</source> | ||
28 | <target>Temps actuel</target> | ||
29 | </trans-unit> | ||
30 | <trans-unit id="Duration"> | ||
31 | <source>Duration</source> | ||
32 | <target>Durée</target> | ||
33 | </trans-unit> | ||
34 | <trans-unit id="Remaining Time"> | ||
35 | <source>Remaining Time</source> | ||
36 | <target>Temps restant</target> | ||
37 | </trans-unit> | ||
38 | <trans-unit id="Stream Type"> | ||
39 | <source>Stream Type</source> | ||
40 | <target>Type de flux</target> | ||
41 | </trans-unit> | ||
42 | <trans-unit id="LIVE"> | ||
43 | <source>LIVE</source> | ||
44 | <target>EN DIRECT</target> | ||
45 | </trans-unit> | ||
46 | <trans-unit id="Loaded"> | ||
47 | <source>Loaded</source> | ||
48 | <target>Chargé</target> | ||
49 | </trans-unit> | ||
50 | <trans-unit id="Progress"> | ||
51 | <source>Progress</source> | ||
52 | <target>Progression</target> | ||
53 | </trans-unit> | ||
54 | <trans-unit id="Progress Bar"> | ||
55 | <source>Progress Bar</source> | ||
56 | <target>Barre de progression</target> | ||
57 | </trans-unit> | ||
58 | <trans-unit id="progress bar timing: currentTime={1} duration={2}"> | ||
59 | <source>{1} of {2}</source> | ||
60 | <target>{1} de {2}</target> | ||
61 | </trans-unit> | ||
62 | <trans-unit id="Fullscreen"> | ||
63 | <source>Fullscreen</source> | ||
64 | <target>Plein écran</target> | ||
65 | </trans-unit> | ||
66 | <trans-unit id="Non-Fullscreen"> | ||
67 | <source>Non-Fullscreen</source> | ||
68 | <target>Fenêtré</target> | ||
69 | </trans-unit> | ||
70 | <trans-unit id="Mute"> | ||
71 | <source>Mute</source> | ||
72 | <target>Sourdine</target> | ||
73 | </trans-unit> | ||
74 | <trans-unit id="Unmute"> | ||
75 | <source>Unmute</source> | ||
76 | <target>Son activé</target> | ||
77 | </trans-unit> | ||
78 | <trans-unit id="Playback Rate"> | ||
79 | <source>Playback Rate</source> | ||
80 | <target>Vitesse de lecture</target> | ||
81 | </trans-unit> | ||
82 | <trans-unit id="Subtitles"> | ||
83 | <source>Subtitles</source> | ||
84 | <target>Sous-titres</target> | ||
85 | </trans-unit> | ||
86 | <trans-unit id="subtitles off"> | ||
87 | <source>subtitles off</source> | ||
88 | <target>Sous-titres désactivés</target> | ||
89 | </trans-unit> | ||
90 | <trans-unit id="Captions"> | ||
91 | <source>Captions</source> | ||
92 | <target>Sous-titres transcrits</target> | ||
93 | </trans-unit> | ||
94 | <trans-unit id="captions off"> | ||
95 | <source>captions off</source> | ||
96 | <target>Sous-titres transcrits désactivés</target> | ||
97 | </trans-unit> | ||
98 | <trans-unit id="Chapters"> | ||
99 | <source>Chapters</source> | ||
100 | <target>Chapitres</target> | ||
101 | </trans-unit> | ||
102 | <trans-unit id="Descriptions"> | ||
103 | <source>Descriptions</source> | ||
104 | <target>Descriptions</target> | ||
105 | </trans-unit> | ||
106 | <trans-unit id="descriptions off"> | ||
107 | <source>descriptions off</source> | ||
108 | <target>descriptions désactivées</target> | ||
109 | </trans-unit> | ||
110 | <trans-unit id="Audio Track"> | ||
111 | <source>Audio Track</source> | ||
112 | <target>Piste audio</target> | ||
113 | </trans-unit> | ||
114 | <trans-unit id="Volume Level"> | ||
115 | <source>Volume Level</source> | ||
116 | <target>Niveau de volume</target> | ||
117 | </trans-unit> | ||
118 | <trans-unit id="You aborted the media playback"> | ||
119 | <source>You aborted the media playback</source> | ||
120 | <target>Vous avez interrompu la lecture de la vidéo.</target> | ||
121 | </trans-unit> | ||
122 | <trans-unit id="A network error caused the media download to fail part-way."> | ||
123 | <source>A network error caused the media download to fail part-way.</source> | ||
124 | <target>Une erreur de réseau a interrompu le téléchargement de la vidéo.</target> | ||
125 | </trans-unit> | ||
126 | <trans-unit id="The media could not be loaded, either because the server or network failed or because the format is not supported."> | ||
127 | <source>The media could not be loaded, either because the server or network failed or because the format is not supported.</source> | ||
128 | <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> | ||
129 | </trans-unit> | ||
130 | <trans-unit id="The media playback was aborted due to a corruption problem or because the media used features your browser did not support."> | ||
131 | <source>The media playback was aborted due to a corruption problem or because the media used features your browser did not support.</source> | ||
132 | <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> | ||
133 | </trans-unit> | ||
134 | <trans-unit id="No compatible source was found for this media."> | ||
135 | <source>No compatible source was found for this media.</source> | ||
136 | <target>Aucune source compatible n'a été trouvée pour cette vidéo.</target> | ||
137 | </trans-unit> | ||
138 | <trans-unit id="The media is encrypted and we do not have the keys to decrypt it."> | ||
139 | <source>The media is encrypted and we do not have the keys to decrypt it.</source> | ||
140 | <target>Le média est chiffré et nous n'avons pas les clés pour le déchiffrer.</target> | ||
141 | </trans-unit> | ||
142 | <trans-unit id="Play Video"> | ||
143 | <source>Play Video</source> | ||
144 | <target>Lire la vidéo</target> | ||
145 | </trans-unit> | ||
146 | <trans-unit id="Close"> | ||
147 | <source>Close</source> | ||
148 | <target>Fermer</target> | ||
149 | </trans-unit> | ||
150 | <trans-unit id="Close Modal Dialog"> | ||
151 | <source>Close Modal Dialog</source> | ||
152 | <target>Fermer la boîte de dialogue modale</target> | ||
153 | </trans-unit> | ||
154 | <trans-unit id="Modal Window"> | ||
155 | <source>Modal Window</source> | ||
156 | <target>Fenêtre modale</target> | ||
157 | </trans-unit> | ||
158 | <trans-unit id="This is a modal window"> | ||
159 | <source>This is a modal window</source> | ||
160 | <target>Ceci est une fenêtre modale</target> | ||
161 | </trans-unit> | ||
162 | <trans-unit id="This modal can be closed by pressing the Escape key or activating the close button."> | ||
163 | <source>This modal can be closed by pressing the Escape key or activating the close button.</source> | ||
164 | <target>Ce modal peut être fermé en appuyant sur la touche Échap ou activer le bouton de fermeture.</target> | ||
165 | </trans-unit> | ||
166 | <trans-unit id=", opens captions settings dialog"> | ||
167 | <source>, opens captions settings dialog</source> | ||
168 | <target>, ouvrir les paramètres des sous-titres transcrits</target> | ||
169 | </trans-unit> | ||
170 | <trans-unit id=", opens subtitles settings dialog"> | ||
171 | <source>, opens subtitles settings dialog</source> | ||
172 | <target>, ouvrir les paramètres des sous-titres</target> | ||
173 | </trans-unit> | ||
174 | <trans-unit id=", opens descriptions settings dialog"> | ||
175 | <source>, opens descriptions settings dialog</source> | ||
176 | <target>, ouvrir les paramètres des descriptions</target> | ||
177 | </trans-unit> | ||
178 | <trans-unit id=", selected"> | ||
179 | <source>, selected</source> | ||
180 | <target>, sélectionné</target> | ||
181 | </trans-unit> | ||
182 | <trans-unit id="captions settings"> | ||
183 | <source>captions settings</source> | ||
184 | <target>Paramètres des sous-titres transcrits</target> | ||
185 | </trans-unit> | ||
186 | <trans-unit id="subtitles settings"> | ||
187 | <source>subititles settings</source> | ||
188 | <target>Paramètres des sous-titres</target> | ||
189 | </trans-unit> | ||
190 | <trans-unit id="descriptions settings"> | ||
191 | <source>descriptions settings</source> | ||
192 | <target>Paramètres des descriptions</target> | ||
193 | </trans-unit> | ||
194 | <trans-unit id="Text"> | ||
195 | <source>Text</source> | ||
196 | <target>Texte</target> | ||
197 | </trans-unit> | ||
198 | <trans-unit id="White"> | ||
199 | <source>White</source> | ||
200 | <target>Blanc</target> | ||
201 | </trans-unit> | ||
202 | <trans-unit id="Black"> | ||
203 | <source>Black</source> | ||
204 | <target>Noir</target> | ||
205 | </trans-unit> | ||
206 | <trans-unit id="Red"> | ||
207 | <source>Red</source> | ||
208 | <target>Rouge</target> | ||
209 | </trans-unit> | ||
210 | <trans-unit id="Green"> | ||
211 | <source>Green</source> | ||
212 | <target>Vert</target> | ||
213 | </trans-unit> | ||
214 | <trans-unit id="Blue"> | ||
215 | <source>Blue</source> | ||
216 | <target>Bleu</target> | ||
217 | </trans-unit> | ||
218 | <trans-unit id="Yellow"> | ||
219 | <source>Yellow</source> | ||
220 | <target>Jaune</target> | ||
221 | </trans-unit> | ||
222 | <trans-unit id="Magenta"> | ||
223 | <source>Magenta</source> | ||
224 | <target>Magenta</target> | ||
225 | </trans-unit> | ||
226 | <trans-unit id="Cyan"> | ||
227 | <source>Cyan</source> | ||
228 | <target>Cyan</target> | ||
229 | </trans-unit> | ||
230 | <trans-unit id="Background"> | ||
231 | <source>Background</source> | ||
232 | <target>Arrière-plan</target> | ||
233 | </trans-unit> | ||
234 | <trans-unit id="Window"> | ||
235 | <source>Window</source> | ||
236 | <target>Fenêtre</target> | ||
237 | </trans-unit> | ||
238 | <trans-unit id="Transparent"> | ||
239 | <source>Transparent</source> | ||
240 | <target>Transparent</target> | ||
241 | </trans-unit> | ||
242 | <trans-unit id="Semi-Transparent"> | ||
243 | <source>Semi-Transparent</source> | ||
244 | <target>Semi-transparent</target> | ||
245 | </trans-unit> | ||
246 | <trans-unit id="Opaque"> | ||
247 | <source>Opaque</source> | ||
248 | <target>Opaque</target> | ||
249 | </trans-unit> | ||
250 | <trans-unit id="Font Size"> | ||
251 | <source>Font Size</source> | ||
252 | <target>Taille des caractères</target> | ||
253 | </trans-unit> | ||
254 | <trans-unit id="Text Edge Style"> | ||
255 | <source>Text Edge Style</source> | ||
256 | <target>Style des contours du texte</target> | ||
257 | </trans-unit> | ||
258 | <trans-unit id="None"> | ||
259 | <source>None</source> | ||
260 | <target>Aucun</target> | ||
261 | </trans-unit> | ||
262 | <trans-unit id="Raised"> | ||
263 | <source>Raised</source> | ||
264 | <target>Élevé</target> | ||
265 | </trans-unit> | ||
266 | <trans-unit id="Depressed"> | ||
267 | <source>Depressed</source> | ||
268 | <target>Enfoncé</target> | ||
269 | </trans-unit> | ||
270 | <trans-unit id="Uniform"> | ||
271 | <source>Uniform</source> | ||
272 | <target>Uniforme</target> | ||
273 | </trans-unit> | ||
274 | <trans-unit id="Dropshadow"> | ||
275 | <source>Dropshadow</source> | ||
276 | <target>Ombre portée</target> | ||
277 | </trans-unit> | ||
278 | <trans-unit id="Font Family"> | ||
279 | <source>Font Family</source> | ||
280 | <target>Familles de polices</target> | ||
281 | </trans-unit> | ||
282 | <trans-unit id="Proportional Sans-Serif"> | ||
283 | <source>Proportional Sans-Serif</source> | ||
284 | <target>Polices à chasse variable sans empattement (Proportional Sans-Serif)</target> | ||
285 | </trans-unit> | ||
286 | <trans-unit id="Monospace Sans-Serif"> | ||
287 | <source>Monospace Sans-Serif</source> | ||
288 | <target>Polices à chasse fixe sans empattement (Monospace Sans-Serif)</target> | ||
289 | </trans-unit> | ||
290 | <trans-unit id="Proportional Serif"> | ||
291 | <source>Proportional Serif</source> | ||
292 | <target>Polices à chasse variable avec empattement (Proportional Serif)</target> | ||
293 | </trans-unit> | ||
294 | <trans-unit id="Monospace Serif"> | ||
295 | <source>Monospace Serif</source> | ||
296 | <target>Polices à chasse fixe avec empattement (Monospace Serif)</target> | ||
297 | </trans-unit> | ||
298 | <trans-unit id="Casual"> | ||
299 | <source>Casual</source> | ||
300 | <target>Manuscrite</target> | ||
301 | </trans-unit> | ||
302 | <trans-unit id="Script"> | ||
303 | <source>Script</source> | ||
304 | <target>Scripte</target> | ||
305 | </trans-unit> | ||
306 | <trans-unit id="Small Caps"> | ||
307 | <source>Small Caps</source> | ||
308 | <target>Petites capitales</target> | ||
309 | </trans-unit> | ||
310 | <trans-unit id="Reset"> | ||
311 | <source>Reset</source> | ||
312 | <target>Réinitialiser</target> | ||
313 | </trans-unit> | ||
314 | <trans-unit id="restore all settings to the default values"> | ||
315 | <source>restore all settings to the default values</source> | ||
316 | <target>Restaurer tous les paramètres aux valeurs par défaut</target> | ||
317 | </trans-unit> | ||
318 | <trans-unit id="Done"> | ||
319 | <source>Done</source> | ||
320 | <target>Terminé</target> | ||
321 | </trans-unit> | ||
322 | <trans-unit id="Caption Settings Dialog"> | ||
323 | <source>Caption Settings Dialog</source> | ||
324 | <target>Boîte de dialogue des paramètres des sous-titres transcrits</target> | ||
325 | </trans-unit> | ||
326 | <trans-unit id="Beginning of dialog window. Escape will cancel and close the window."> | ||
327 | <source>Beginning of dialog window. Escape will cancel and close the window.</source> | ||
328 | <target>Début de la fenêtre de dialogue. La touche d'échappement annulera et fermera la fenêtre.</target> | ||
329 | </trans-unit> | ||
330 | <trans-unit id="End of dialog window."> | ||
331 | <source>End of dialog window.</source> | ||
332 | <target>Fin de la fenêtre de dialogue.</target> | ||
333 | </trans-unit> | ||
334 | <trans-unit id="{1} is loading."> | ||
335 | <source>{1} is loading.</source> | ||
336 | <target>{1} est en train de charger</target> | ||
337 | </trans-unit> | ||
338 | <trans-unit id="Quality"> | ||
339 | <source>Quality</source> | ||
340 | <target>Qualité</target> | ||
341 | </trans-unit> | ||
342 | <trans-unit id="Auto"> | ||
343 | <source>Auto</source> | ||
344 | <target>Auto</target> | ||
345 | </trans-unit> | ||
346 | <trans-unit id="Speed"> | ||
347 | <source>Speed</source> | ||
348 | <target>Vitesse</target> | ||
349 | </trans-unit> | ||
350 | <trans-unit id="peers"> | ||
351 | <source>peers</source> | ||
352 | <target>pairs</target> | ||
353 | </trans-unit> | ||
354 | <trans-unit id="Go to the video page"> | ||
355 | <source>Go to the video page</source> | ||
356 | <target>Aller sur la page de la vidéo</target> | ||
357 | </trans-unit> | ||
358 | <trans-unit id="Settings"> | ||
359 | <source>Settings</source> | ||
360 | <target>Paramètres</target> | ||
361 | </trans-unit> | ||
362 | <trans-unit id="Uses P2P, others may know you are watching this video."> | ||
363 | <source>Uses P2P, others may know you are watching this video.</source> | ||
364 | <target>Utilise le P2P, d'autres personnes pourraient savoir que vous regardez cette vidéo.</target> | ||
365 | </trans-unit> | ||
366 | <trans-unit id="Copy the video URL"> | ||
367 | <source>Copy the video URL</source> | ||
368 | <target>Copier le lien de la vidéo</target> | ||
369 | </trans-unit> | ||
370 | <trans-unit id="Copy the video URL at the current time"> | ||
371 | <source>Copy the video URL at the current time</source> | ||
372 | <target>Copier le lien de la vidéo à partir de cette séquence</target> | ||
373 | </trans-unit> | ||
374 | <trans-unit id="Copy embed code"> | ||
375 | <source>Copy embed code</source> | ||
376 | <target>Copier le code d'intégration</target> | ||
377 | </trans-unit> | ||
378 | </body> | ||
379 | </file></xliff> \ No newline at end of file | ||
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index d603690ca..166013226 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts | |||
@@ -14,14 +14,14 @@ import 'core-js/es6/regexp' | |||
14 | import 'core-js/es6/map' | 14 | import 'core-js/es6/map' |
15 | import 'core-js/es6/weak-map' | 15 | import 'core-js/es6/weak-map' |
16 | import 'core-js/es6/set' | 16 | import 'core-js/es6/set' |
17 | |||
18 | // For google bot that uses Chrome 41 and does not understand fetch | 17 | // For google bot that uses Chrome 41 and does not understand fetch |
19 | import 'whatwg-fetch' | 18 | import 'whatwg-fetch' |
20 | 19 | ||
21 | import * as videojs from 'video.js' | 20 | import * as videojs from 'video.js' |
22 | 21 | ||
23 | import { VideoDetails } from '../../../../shared' | 22 | import { VideoDetails } from '../../../../shared' |
24 | import { getVideojsOptions } from '../../assets/player/peertube-player' | 23 | import { addContextMenu, getVideojsOptions, loadLocale } from '../../assets/player/peertube-player' |
24 | import { environment } from '../../environments/environment' | ||
25 | 25 | ||
26 | function getVideoUrl (id: string) { | 26 | function getVideoUrl (id: string) { |
27 | return window.location.origin + '/api/v1/videos/' + id | 27 | return window.location.origin + '/api/v1/videos/' + id |
@@ -61,7 +61,8 @@ function videoFetchError (videoElement: HTMLVideoElement) { | |||
61 | const urlParts = window.location.href.split('/') | 61 | const urlParts = window.location.href.split('/') |
62 | const videoId = urlParts[urlParts.length - 1] | 62 | const videoId = urlParts[urlParts.length - 1] |
63 | 63 | ||
64 | loadVideoInfo(videoId) | 64 | loadLocale(environment.apiUrl, videojs, navigator.language) |
65 | .then(() => loadVideoInfo(videoId)) | ||
65 | .then(async response => { | 66 | .then(async response => { |
66 | const videoContainerId = 'video-container' | 67 | const videoContainerId = 'video-container' |
67 | const videoElement = document.getElementById(videoContainerId) as HTMLVideoElement | 68 | const videoElement = document.getElementById(videoContainerId) as HTMLVideoElement |
@@ -91,7 +92,6 @@ loadVideoInfo(videoId) | |||
91 | const videojsOptions = getVideojsOptions({ | 92 | const videojsOptions = getVideojsOptions({ |
92 | autoplay, | 93 | autoplay, |
93 | inactivityTimeout: 1500, | 94 | inactivityTimeout: 1500, |
94 | videoEmbedUrl: window.location.origin + videoInfo.embedPath, | ||
95 | videoViewUrl: getVideoUrl(videoId) + '/views', | 95 | videoViewUrl: getVideoUrl(videoId) + '/views', |
96 | playerElement: videoElement, | 96 | playerElement: videoElement, |
97 | videoFiles: videoInfo.files, | 97 | videoFiles: videoInfo.files, |
@@ -106,8 +106,10 @@ loadVideoInfo(videoId) | |||
106 | 106 | ||
107 | player.dock({ | 107 | player.dock({ |
108 | title: videoInfo.name, | 108 | title: videoInfo.name, |
109 | description: 'Uses P2P, others may know you are watching this video.' | 109 | description: player.localize('Uses P2P, others may know you are watching this video.') |
110 | }) | 110 | }) |
111 | |||
112 | addContextMenu(player, window.location.origin + videoInfo.embedPath) | ||
111 | }) | 113 | }) |
112 | }) | 114 | }) |
113 | .catch(err => console.error(err)) | 115 | .catch(err => console.error(err)) |
diff --git a/package.json b/package.json index 21701e664..707579af3 100644 --- a/package.json +++ b/package.json | |||
@@ -30,6 +30,8 @@ | |||
30 | "danger:clean:prod": "scripty", | 30 | "danger:clean:prod": "scripty", |
31 | "danger:clean:modules": "scripty", | 31 | "danger:clean:modules": "scripty", |
32 | "i18n:generate": "scripty", | 32 | "i18n:generate": "scripty", |
33 | "i18n:xliff2json": "node ./dist/scripts/i18n/xliff2json.js", | ||
34 | "i18n:create-custom-files": "node ./dist/scripts/i18n/create-custom-files.js", | ||
33 | "reset-password": "node ./dist/scripts/reset-password.js", | 35 | "reset-password": "node ./dist/scripts/reset-password.js", |
34 | "play": "scripty", | 36 | "play": "scripty", |
35 | "dev": "scripty", | 37 | "dev": "scripty", |
@@ -174,6 +176,7 @@ | |||
174 | "tslint-config-standard": "^7.0.0", | 176 | "tslint-config-standard": "^7.0.0", |
175 | "typescript": "^2.5.2", | 177 | "typescript": "^2.5.2", |
176 | "webtorrent": "^0.100.0", | 178 | "webtorrent": "^0.100.0", |
179 | "xliff": "^3.0.1", | ||
177 | "youtube-dl": "^1.12.2" | 180 | "youtube-dl": "^1.12.2" |
178 | }, | 181 | }, |
179 | "scripty": { | 182 | "scripty": { |
diff --git a/scripts/i18n/create-custom-files.ts b/scripts/i18n/create-custom-files.ts new file mode 100755 index 000000000..3895b3b9d --- /dev/null +++ b/scripts/i18n/create-custom-files.ts | |||
@@ -0,0 +1,49 @@ | |||
1 | import * as jsToXliff12 from 'xliff/jsToXliff12' | ||
2 | import { writeFile } from 'fs' | ||
3 | import { join } from 'path' | ||
4 | |||
5 | // First, the player | ||
6 | const playerSource = join(__dirname, '../../../client/src/locale/source/videojs_en_US.json') | ||
7 | const playerTarget = join(__dirname, '../../../client/src/locale/source/player_en_US.xml') | ||
8 | |||
9 | const videojs = require(playerSource) | ||
10 | const playerKeys = { | ||
11 | 'Quality': 'Quality', | ||
12 | 'Auto': 'Auto', | ||
13 | 'Speed': 'Speed', | ||
14 | 'peers': 'peers', | ||
15 | 'Go to the video page': 'Go to the video page', | ||
16 | 'Settings': 'Settings', | ||
17 | 'Uses P2P, others may know you are watching this video.': 'Uses P2P, others may know you are watching this video.', | ||
18 | 'Copy the video URL': 'Copy the video URL', | ||
19 | 'Copy the video URL at the current time': 'Copy the video URL at the current time', | ||
20 | 'Copy embed code': 'Copy embed code' | ||
21 | } | ||
22 | |||
23 | const obj = { | ||
24 | resources: { | ||
25 | namespace1: {} | ||
26 | } | ||
27 | } | ||
28 | |||
29 | for (const sourceObject of [ videojs, playerKeys ]) { | ||
30 | Object.keys(sourceObject).forEach(k => obj.resources.namespace1[ k ] = { source: sourceObject[ k ] }) | ||
31 | } | ||
32 | |||
33 | jsToXliff12(obj, (err, res) => { | ||
34 | if (err) { | ||
35 | console.error(err) | ||
36 | process.exit(-1) | ||
37 | } | ||
38 | |||
39 | writeFile(playerTarget, res, err => { | ||
40 | if (err) { | ||
41 | console.error(err) | ||
42 | process.exit(-1) | ||
43 | } | ||
44 | |||
45 | process.exit(0) | ||
46 | }) | ||
47 | }) | ||
48 | |||
49 | // Then, the server strings | ||
diff --git a/scripts/i18n/generate.sh b/scripts/i18n/generate.sh index f8ad8a3c1..0a5b6dee1 100755 --- a/scripts/i18n/generate.sh +++ b/scripts/i18n/generate.sh | |||
@@ -9,4 +9,8 @@ npm run ngx-extractor -- --locale "en-US" -i 'src/**/*.ts' -f xlf -o src/locale/ | |||
9 | # Zanata does not support inner elements in <source>, so we hack these special elements | 9 | # Zanata does not support inner elements in <source>, so we hack these special elements |
10 | # This regex translate the Angular elements to special entities (that we will reconvert on pull) | 10 | # This regex translate the Angular elements to special entities (that we will reconvert on pull) |
11 | #sed -i 's/<x id=\(.\+\?\)\/>/\<x id=\1\/\>/g' src/locale/source/messages_en_US.xml | 11 | #sed -i 's/<x id=\(.\+\?\)\/>/\<x id=\1\/\>/g' src/locale/source/messages_en_US.xml |
12 | perl -pi -e 's|<x id=(.+?)/>|<x id=\1/>|g' src/locale/source/messages_en_US.xml \ No newline at end of file | 12 | perl -pi -e 's|<x id=(.+?)/>|<x id=\1/>|g' src/locale/source/messages_en_US.xml |
13 | |||
14 | # Add our strings too | ||
15 | cd ../ | ||
16 | npm run i18n:create-custom-files \ No newline at end of file | ||
diff --git a/scripts/i18n/pull-hook.sh b/scripts/i18n/pull-hook.sh index bbe4a813e..dec426b88 100755 --- a/scripts/i18n/pull-hook.sh +++ b/scripts/i18n/pull-hook.sh | |||
@@ -7,5 +7,7 @@ set -eu | |||
7 | #sed -i 's/\<x id=\(.\+\?\)\/\>/<x id=\1\/>/g' client/src/locale/target/* | 7 | #sed -i 's/\<x id=\(.\+\?\)\/\>/<x id=\1\/>/g' client/src/locale/target/* |
8 | 8 | ||
9 | for i in 1 2 3; do | 9 | for i in 1 2 3; do |
10 | perl -pi -e 's|<x id=(.+?)/>([^"])|<x id=\1/>\2|g' client/src/locale/target/* | 10 | perl -pi -e 's|<x id=(.+?)/>([^"])|<x id=\1/>\2|g' client/src/locale/target/*.xml |
11 | done \ No newline at end of file | 11 | done |
12 | |||
13 | npm run i18n:xliff2json \ No newline at end of file | ||
diff --git a/scripts/i18n/xliff2json.ts b/scripts/i18n/xliff2json.ts new file mode 100755 index 000000000..34784ac11 --- /dev/null +++ b/scripts/i18n/xliff2json.ts | |||
@@ -0,0 +1,42 @@ | |||
1 | import * as xliff12ToJs from 'xliff/xliff12ToJs' | ||
2 | import { readFileSync, writeFile } from 'fs' | ||
3 | import { join } from 'path' | ||
4 | |||
5 | // First, the player | ||
6 | const playerSource = join(__dirname, '../../../client/src/locale/target/player_fr.xml') | ||
7 | const playerTarget = join(__dirname, '../../../client/src/locale/target/player_fr.json') | ||
8 | |||
9 | // Remove the two first lines our xliff module does not like | ||
10 | let playerFile = readFileSync(playerSource).toString() | ||
11 | playerFile = removeFirstLine(playerFile) | ||
12 | playerFile = removeFirstLine(playerFile) | ||
13 | |||
14 | xliff12ToJs(playerFile, (err, res) => { | ||
15 | if (err) { | ||
16 | console.error(err) | ||
17 | process.exit(-1) | ||
18 | } | ||
19 | |||
20 | const json = createJSONString(res) | ||
21 | writeFile(playerTarget, json, err => { | ||
22 | if (err) { | ||
23 | console.error(err) | ||
24 | process.exit(-1) | ||
25 | } | ||
26 | |||
27 | process.exit(0) | ||
28 | }) | ||
29 | }) | ||
30 | |||
31 | function removeFirstLine (str: string) { | ||
32 | return str.substring(str.indexOf('\n') + 1) | ||
33 | } | ||
34 | |||
35 | function createJSONString (obj: any) { | ||
36 | const res: any = {} | ||
37 | const strings = obj.resources[''] | ||
38 | |||
39 | Object.keys(strings).forEach(k => res[k] = strings[k].target) | ||
40 | |||
41 | return JSON.stringify(res) | ||
42 | } | ||
diff --git a/scripts/watch/server.sh b/scripts/watch/server.sh index 6250fb9a4..badbf3da0 100755 --- a/scripts/watch/server.sh +++ b/scripts/watch/server.sh | |||
@@ -2,6 +2,11 @@ | |||
2 | 2 | ||
3 | set -eu | 3 | set -eu |
4 | 4 | ||
5 | # Copy locales | ||
6 | mkdir -p "./client/dist" | ||
7 | rm -r "./client/dist/locale" | ||
8 | cp -r "./client/src/locale/target" "./client/dist/locale" | ||
9 | |||
5 | NODE_ENV=test concurrently -k \ | 10 | NODE_ENV=test concurrently -k \ |
6 | "npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \ | 11 | "npm run tsc -- --sourceMap && npm run nodemon -- --delay 2 --watch ./dist dist/server" \ |
7 | "npm run tsc -- --sourceMap --preserveWatchOutput -w" | 12 | "npm run tsc -- --sourceMap --preserveWatchOutput -w" |
diff --git a/server/controllers/client.ts b/server/controllers/client.ts index 4b37b5fa6..b153f6086 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts | |||
@@ -47,6 +47,14 @@ for (const staticClientFile of staticClientFiles) { | |||
47 | clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) | 47 | clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) |
48 | clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE })) | 48 | clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE })) |
49 | 49 | ||
50 | clientsRouter.use('/client/locales/:locale/:file.json', function (req, res) { | ||
51 | if (req.params.locale === 'fr' && req.params.file === 'player') { | ||
52 | return res.sendFile(join(__dirname, '../../../client/dist/locale/player_fr.json')) | ||
53 | } | ||
54 | |||
55 | return res.sendStatus(404) | ||
56 | }) | ||
57 | |||
50 | // 404 for static files not found | 58 | // 404 for static files not found |
51 | clientsRouter.use('/client/*', (req: express.Request, res: express.Response, next: express.NextFunction) => { | 59 | clientsRouter.use('/client/*', (req: express.Request, res: express.Response, next: express.NextFunction) => { |
52 | res.sendStatus(404) | 60 | res.sendStatus(404) |
diff --git a/shared/models/i18n/i18n.ts b/shared/models/i18n/i18n.ts index 2d3a1d3e2..4d50bc36e 100644 --- a/shared/models/i18n/i18n.ts +++ b/shared/models/i18n/i18n.ts | |||
@@ -7,6 +7,10 @@ export function getDefaultLocale () { | |||
7 | return 'en-US' | 7 | return 'en-US' |
8 | } | 8 | } |
9 | 9 | ||
10 | export function isDefaultLocale (locale: string) { | ||
11 | return locale === getDefaultLocale() | ||
12 | } | ||
13 | |||
10 | const possiblePaths = Object.keys(I18N_LOCALES).map(l => '/' + l) | 14 | const possiblePaths = Object.keys(I18N_LOCALES).map(l => '/' + l) |
11 | export function is18nPath (path: string) { | 15 | export function is18nPath (path: string) { |
12 | return possiblePaths.indexOf(path) !== -1 | 16 | return possiblePaths.indexOf(path) !== -1 |
@@ -8402,6 +8402,18 @@ xhr2@^0.1.4: | |||
8402 | version "0.1.4" | 8402 | version "0.1.4" |
8403 | resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" | 8403 | resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" |
8404 | 8404 | ||
8405 | xliff@^3.0.1: | ||
8406 | version "3.0.1" | ||
8407 | resolved "https://registry.yarnpkg.com/xliff/-/xliff-3.0.1.tgz#ea0f5840011727aecbddf111e5c26d8590dcca9b" | ||
8408 | dependencies: | ||
8409 | xml-js "1.6.2" | ||
8410 | |||
8411 | xml-js@1.6.2: | ||
8412 | version "1.6.2" | ||
8413 | resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.2.tgz#4c4cb8413998f73701a202a1b8b2f17c985a72c5" | ||
8414 | dependencies: | ||
8415 | sax "^1.2.4" | ||
8416 | |||
8405 | xml-name-validator@^3.0.0: | 8417 | xml-name-validator@^3.0.0: |
8406 | version "3.0.0" | 8418 | version "3.0.0" |
8407 | resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" | 8419 | resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" |