aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-07-26 14:44:50 +0200
committerChocobozzz <me@florianbigard.com>2019-07-26 15:18:30 +0200
commitd75db01f14138ea660c4c519e37ab05228b39d13 (patch)
tree85a3da315ea6e1501fec5b70790482504dd64793 /client
parentee286591a5b740702bad66c55cc900740f749e9a (diff)
downloadPeerTube-d75db01f14138ea660c4c519e37ab05228b39d13.tar.gz
PeerTube-d75db01f14138ea660c4c519e37ab05228b39d13.tar.zst
PeerTube-d75db01f14138ea660c4c519e37ab05228b39d13.zip
Add plugin translation system
Diffstat (limited to 'client')
-rw-r--r--client/src/app/+admin/plugins/shared/plugin-api.service.ts25
-rw-r--r--client/src/app/core/plugins/plugin.service.ts42
-rw-r--r--client/src/app/shared/video/video.service.ts1
-rw-r--r--client/src/types/register-client-option.model.ts12
4 files changed, 64 insertions, 16 deletions
diff --git a/client/src/app/+admin/plugins/shared/plugin-api.service.ts b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
index c360fc1b3..f6ef68e9c 100644
--- a/client/src/app/+admin/plugins/shared/plugin-api.service.ts
+++ b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
@@ -1,4 +1,4 @@
1import { catchError } from 'rxjs/operators' 1import { catchError, map, switchMap } from 'rxjs/operators'
2import { HttpClient, HttpParams } from '@angular/common/http' 2import { HttpClient, HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core' 3import { Injectable } from '@angular/core'
4import { environment } from '../../../../environments/environment' 4import { environment } from '../../../../environments/environment'
@@ -6,13 +6,14 @@ import { RestExtractor, RestService } from '../../../shared'
6import { I18n } from '@ngx-translate/i18n-polyfill' 6import { I18n } from '@ngx-translate/i18n-polyfill'
7import { PluginType } from '@shared/models/plugins/plugin.type' 7import { PluginType } from '@shared/models/plugins/plugin.type'
8import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 8import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
9import { ResultList } from '@shared/models' 9import { peertubeTranslate, ResultList } from '@shared/models'
10import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' 10import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model'
11import { ManagePlugin } from '@shared/models/plugins/manage-plugin.model' 11import { ManagePlugin } from '@shared/models/plugins/manage-plugin.model'
12import { InstallOrUpdatePlugin } from '@shared/models/plugins/install-plugin.model' 12import { InstallOrUpdatePlugin } from '@shared/models/plugins/install-plugin.model'
13import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' 13import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model'
14import { RegisteredServerSettings, RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' 14import { RegisteredServerSettings, RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model'
15import { PluginService } from '@app/core/plugins/plugin.service' 15import { PluginService } from '@app/core/plugins/plugin.service'
16import { Observable } from 'rxjs'
16 17
17@Injectable() 18@Injectable()
18export class PluginApiService { 19export class PluginApiService {
@@ -92,7 +93,10 @@ export class PluginApiService {
92 const path = PluginApiService.BASE_PLUGIN_URL + '/' + npmName + '/registered-settings' 93 const path = PluginApiService.BASE_PLUGIN_URL + '/' + npmName + '/registered-settings'
93 94
94 return this.authHttp.get<RegisteredServerSettings>(path) 95 return this.authHttp.get<RegisteredServerSettings>(path)
95 .pipe(catchError(res => this.restExtractor.handleError(res))) 96 .pipe(
97 switchMap(res => this.translateSettingsLabel(npmName, res)),
98 catchError(res => this.restExtractor.handleError(res))
99 )
96 } 100 }
97 101
98 updatePluginSettings (pluginName: string, pluginType: PluginType, settings: any) { 102 updatePluginSettings (pluginName: string, pluginType: PluginType, settings: any) {
@@ -129,4 +133,19 @@ export class PluginApiService {
129 return this.authHttp.post(PluginApiService.BASE_PLUGIN_URL + '/install', body) 133 return this.authHttp.post(PluginApiService.BASE_PLUGIN_URL + '/install', body)
130 .pipe(catchError(res => this.restExtractor.handleError(res))) 134 .pipe(catchError(res => this.restExtractor.handleError(res)))
131 } 135 }
136
137 private translateSettingsLabel (npmName: string, res: RegisteredServerSettings): Observable<RegisteredServerSettings> {
138 return this.pluginService.translationsObservable
139 .pipe(
140 map(allTranslations => allTranslations[npmName]),
141 map(translations => {
142 const registeredSettings = res.registeredSettings
143 .map(r => {
144 return Object.assign({}, r, { label: peertubeTranslate(r.label, translations) })
145 })
146
147 return { registeredSettings }
148 })
149 )
150 }
132} 151}
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts
index cca779177..3bb82e8a9 100644
--- a/client/src/app/core/plugins/plugin.service.ts
+++ b/client/src/app/core/plugins/plugin.service.ts
@@ -1,11 +1,11 @@
1import { Injectable, NgZone } from '@angular/core' 1import { Inject, Injectable, LOCALE_ID, NgZone } from '@angular/core'
2import { Router } from '@angular/router' 2import { Router } from '@angular/router'
3import { ServerConfigPlugin } from '@shared/models' 3import { getCompleteLocale, isDefaultLocale, peertubeTranslate, ServerConfigPlugin } from '@shared/models'
4import { ServerService } from '@app/core/server/server.service' 4import { ServerService } from '@app/core/server/server.service'
5import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' 5import { ClientScript } from '@shared/models/plugins/plugin-package-json.model'
6import { ClientScript as ClientScriptModule } from '../../../types/client-script.model' 6import { ClientScript as ClientScriptModule } from '../../../types/client-script.model'
7import { environment } from '../../../environments/environment' 7import { environment } from '../../../environments/environment'
8import { ReplaySubject } from 'rxjs' 8import { Observable, of, ReplaySubject } from 'rxjs'
9import { catchError, first, map, shareReplay } from 'rxjs/operators' 9import { catchError, first, map, shareReplay } from 'rxjs/operators'
10import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' 10import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks'
11import { ClientHook, ClientHookName, clientHookObject } from '@shared/models/plugins/client-hook.model' 11import { ClientHook, ClientHookName, clientHookObject } from '@shared/models/plugins/client-hook.model'
@@ -15,6 +15,9 @@ import { HttpClient } from '@angular/common/http'
15import { RestExtractor } from '@app/shared/rest' 15import { RestExtractor } from '@app/shared/rest'
16import { PluginType } from '@shared/models/plugins/plugin.type' 16import { PluginType } from '@shared/models/plugins/plugin.type'
17import { PublicServerSetting } from '@shared/models/plugins/public-server.setting' 17import { PublicServerSetting } from '@shared/models/plugins/public-server.setting'
18import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
19import { RegisterClientHelpers } from '../../../types/register-client-option.model'
20import { PluginTranslation } from '@shared/models/plugins/plugin-translation.model'
18 21
19interface HookStructValue extends RegisterClientHookOptions { 22interface HookStructValue extends RegisterClientHookOptions {
20 plugin: ServerConfigPlugin 23 plugin: ServerConfigPlugin
@@ -30,7 +33,8 @@ type PluginInfo = {
30 33
31@Injectable() 34@Injectable()
32export class PluginService implements ClientHook { 35export class PluginService implements ClientHook {
33 private static BASE_PLUGIN_URL = environment.apiUrl + '/api/v1/plugins' 36 private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins'
37 private static BASE_PLUGIN_URL = environment.apiUrl + '/plugins'
34 38
35 pluginsBuilt = new ReplaySubject<boolean>(1) 39 pluginsBuilt = new ReplaySubject<boolean>(1)
36 40
@@ -40,6 +44,8 @@ export class PluginService implements ClientHook {
40 'video-watch': new ReplaySubject<boolean>(1) 44 'video-watch': new ReplaySubject<boolean>(1)
41 } 45 }
42 46
47 translationsObservable: Observable<PluginTranslation>
48
43 private plugins: ServerConfigPlugin[] = [] 49 private plugins: ServerConfigPlugin[] = []
44 private scopes: { [ scopeName: string ]: PluginInfo[] } = {} 50 private scopes: { [ scopeName: string ]: PluginInfo[] } = {}
45 private loadedScripts: { [ script: string ]: boolean } = {} 51 private loadedScripts: { [ script: string ]: boolean } = {}
@@ -53,8 +59,10 @@ export class PluginService implements ClientHook {
53 private server: ServerService, 59 private server: ServerService,
54 private zone: NgZone, 60 private zone: NgZone,
55 private authHttp: HttpClient, 61 private authHttp: HttpClient,
56 private restExtractor: RestExtractor 62 private restExtractor: RestExtractor,
63 @Inject(LOCALE_ID) private localeId: string
57 ) { 64 ) {
65 this.loadTranslations()
58 } 66 }
59 67
60 initializePlugins () { 68 initializePlugins () {
@@ -235,8 +243,9 @@ export class PluginService implements ClientHook {
235 } 243 }
236 } 244 }
237 245
238 private buildPeerTubeHelpers (pluginInfo: PluginInfo) { 246 private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers {
239 const { plugin } = pluginInfo 247 const { plugin } = pluginInfo
248 const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
240 249
241 return { 250 return {
242 getBaseStaticRoute: () => { 251 getBaseStaticRoute: () => {
@@ -245,8 +254,7 @@ export class PluginService implements ClientHook {
245 }, 254 },
246 255
247 getSettings: () => { 256 getSettings: () => {
248 const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) 257 const path = PluginService.BASE_PLUGIN_API_URL + '/' + npmName + '/public-settings'
249 const path = PluginService.BASE_PLUGIN_URL + '/' + npmName + '/public-settings'
250 258
251 return this.authHttp.get<PublicServerSetting>(path) 259 return this.authHttp.get<PublicServerSetting>(path)
252 .pipe( 260 .pipe(
@@ -254,10 +262,28 @@ export class PluginService implements ClientHook {
254 catchError(res => this.restExtractor.handleError(res)) 262 catchError(res => this.restExtractor.handleError(res))
255 ) 263 )
256 .toPromise() 264 .toPromise()
265 },
266
267 translate: (value: string) => {
268 return this.translationsObservable
269 .pipe(map(allTranslations => allTranslations[npmName]))
270 .pipe(map(translations => peertubeTranslate(value, translations)))
271 .toPromise()
257 } 272 }
258 } 273 }
259 } 274 }
260 275
276 private loadTranslations () {
277 const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId)
278
279 // Default locale, nothing to translate
280 if (isDefaultLocale(completeLocale)) this.translationsObservable = of({}).pipe(shareReplay())
281
282 this.translationsObservable = this.authHttp
283 .get<PluginTranslation>(PluginService.BASE_PLUGIN_URL + '/translations/' + completeLocale + '.json')
284 .pipe(shareReplay())
285 }
286
261 private getPluginPathPrefix (isTheme: boolean) { 287 private getPluginPathPrefix (isTheme: boolean) {
262 return isTheme ? '/themes' : '/plugins' 288 return isTheme ? '/themes' : '/plugins'
263 } 289 }
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index d1af13c93..114b014ad 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -31,7 +31,6 @@ import { ServerService } from '@app/core'
31import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' 31import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service'
32import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 32import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
33import { I18n } from '@ngx-translate/i18n-polyfill' 33import { I18n } from '@ngx-translate/i18n-polyfill'
34import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
35import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' 34import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
36 35
37export interface VideosProvider { 36export interface VideosProvider {
diff --git a/client/src/types/register-client-option.model.ts b/client/src/types/register-client-option.model.ts
index 473c2500f..243d74dea 100644
--- a/client/src/types/register-client-option.model.ts
+++ b/client/src/types/register-client-option.model.ts
@@ -3,9 +3,13 @@ import { RegisterClientHookOptions } from '@shared/models/plugins/register-clien
3export type RegisterClientOptions = { 3export type RegisterClientOptions = {
4 registerHook: (options: RegisterClientHookOptions) => void 4 registerHook: (options: RegisterClientHookOptions) => void
5 5
6 peertubeHelpers: { 6 peertubeHelpers: RegisterClientHelpers
7 getBaseStaticRoute: () => string 7}
8
9export type RegisterClientHelpers = {
10 getBaseStaticRoute: () => string
11
12 getSettings: () => Promise<{ [ name: string ]: string }>
8 13
9 getSettings: () => Promise<{ [ name: string ]: string }> 14 translate: (toTranslate: string) => Promise<string>
10 }
11} 15}