diff options
author | Chocobozzz <me@florianbigard.com> | 2019-07-26 14:44:50 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2019-07-26 15:18:30 +0200 |
commit | d75db01f14138ea660c4c519e37ab05228b39d13 (patch) | |
tree | 85a3da315ea6e1501fec5b70790482504dd64793 /client | |
parent | ee286591a5b740702bad66c55cc900740f749e9a (diff) | |
download | PeerTube-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.ts | 25 | ||||
-rw-r--r-- | client/src/app/core/plugins/plugin.service.ts | 42 | ||||
-rw-r--r-- | client/src/app/shared/video/video.service.ts | 1 | ||||
-rw-r--r-- | client/src/types/register-client-option.model.ts | 12 |
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 @@ | |||
1 | import { catchError } from 'rxjs/operators' | 1 | import { catchError, map, switchMap } from 'rxjs/operators' |
2 | import { HttpClient, HttpParams } from '@angular/common/http' | 2 | import { HttpClient, HttpParams } from '@angular/common/http' |
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { environment } from '../../../../environments/environment' | 4 | import { environment } from '../../../../environments/environment' |
@@ -6,13 +6,14 @@ import { RestExtractor, RestService } from '../../../shared' | |||
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | 6 | import { I18n } from '@ngx-translate/i18n-polyfill' |
7 | import { PluginType } from '@shared/models/plugins/plugin.type' | 7 | import { PluginType } from '@shared/models/plugins/plugin.type' |
8 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | 8 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' |
9 | import { ResultList } from '@shared/models' | 9 | import { peertubeTranslate, ResultList } from '@shared/models' |
10 | import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' | 10 | import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' |
11 | import { ManagePlugin } from '@shared/models/plugins/manage-plugin.model' | 11 | import { ManagePlugin } from '@shared/models/plugins/manage-plugin.model' |
12 | import { InstallOrUpdatePlugin } from '@shared/models/plugins/install-plugin.model' | 12 | import { InstallOrUpdatePlugin } from '@shared/models/plugins/install-plugin.model' |
13 | import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' | 13 | import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' |
14 | import { RegisteredServerSettings, RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' | 14 | import { RegisteredServerSettings, RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' |
15 | import { PluginService } from '@app/core/plugins/plugin.service' | 15 | import { PluginService } from '@app/core/plugins/plugin.service' |
16 | import { Observable } from 'rxjs' | ||
16 | 17 | ||
17 | @Injectable() | 18 | @Injectable() |
18 | export class PluginApiService { | 19 | export 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 @@ | |||
1 | import { Injectable, NgZone } from '@angular/core' | 1 | import { Inject, Injectable, LOCALE_ID, NgZone } from '@angular/core' |
2 | import { Router } from '@angular/router' | 2 | import { Router } from '@angular/router' |
3 | import { ServerConfigPlugin } from '@shared/models' | 3 | import { getCompleteLocale, isDefaultLocale, peertubeTranslate, ServerConfigPlugin } from '@shared/models' |
4 | import { ServerService } from '@app/core/server/server.service' | 4 | import { ServerService } from '@app/core/server/server.service' |
5 | import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' | 5 | import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' |
6 | import { ClientScript as ClientScriptModule } from '../../../types/client-script.model' | 6 | import { ClientScript as ClientScriptModule } from '../../../types/client-script.model' |
7 | import { environment } from '../../../environments/environment' | 7 | import { environment } from '../../../environments/environment' |
8 | import { ReplaySubject } from 'rxjs' | 8 | import { Observable, of, ReplaySubject } from 'rxjs' |
9 | import { catchError, first, map, shareReplay } from 'rxjs/operators' | 9 | import { catchError, first, map, shareReplay } from 'rxjs/operators' |
10 | import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' | 10 | import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' |
11 | import { ClientHook, ClientHookName, clientHookObject } from '@shared/models/plugins/client-hook.model' | 11 | import { ClientHook, ClientHookName, clientHookObject } from '@shared/models/plugins/client-hook.model' |
@@ -15,6 +15,9 @@ import { HttpClient } from '@angular/common/http' | |||
15 | import { RestExtractor } from '@app/shared/rest' | 15 | import { RestExtractor } from '@app/shared/rest' |
16 | import { PluginType } from '@shared/models/plugins/plugin.type' | 16 | import { PluginType } from '@shared/models/plugins/plugin.type' |
17 | import { PublicServerSetting } from '@shared/models/plugins/public-server.setting' | 17 | import { PublicServerSetting } from '@shared/models/plugins/public-server.setting' |
18 | import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' | ||
19 | import { RegisterClientHelpers } from '../../../types/register-client-option.model' | ||
20 | import { PluginTranslation } from '@shared/models/plugins/plugin-translation.model' | ||
18 | 21 | ||
19 | interface HookStructValue extends RegisterClientHookOptions { | 22 | interface HookStructValue extends RegisterClientHookOptions { |
20 | plugin: ServerConfigPlugin | 23 | plugin: ServerConfigPlugin |
@@ -30,7 +33,8 @@ type PluginInfo = { | |||
30 | 33 | ||
31 | @Injectable() | 34 | @Injectable() |
32 | export class PluginService implements ClientHook { | 35 | export 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' | |||
31 | import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' | 31 | import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' |
32 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | 32 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' |
33 | import { I18n } from '@ngx-translate/i18n-polyfill' | 33 | import { I18n } from '@ngx-translate/i18n-polyfill' |
34 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | ||
35 | import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' | 34 | import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' |
36 | 35 | ||
37 | export interface VideosProvider { | 36 | export 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 | |||
3 | export type RegisterClientOptions = { | 3 | export type RegisterClientOptions = { |
4 | registerHook: (options: RegisterClientHookOptions) => void | 4 | registerHook: (options: RegisterClientHookOptions) => void |
5 | 5 | ||
6 | peertubeHelpers: { | 6 | peertubeHelpers: RegisterClientHelpers |
7 | getBaseStaticRoute: () => string | 7 | } |
8 | |||
9 | export 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 | } |