Translate plugin settings

This commit is contained in:
Chocobozzz 2021-12-29 14:08:07 +01:00
parent 2accfdd8ec
commit fb3c9e2bf5
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
7 changed files with 57 additions and 39 deletions

View File

@ -126,25 +126,9 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
private async translateSettings (settings: RegisterServerSettingOptions[]) {
for (const setting of settings) {
for (const key of [ 'label', 'html', 'descriptionHTML' ]) {
if (setting[key]) setting[key] = await this.pluginService.translateBy(this.npmName, setting[key])
}
if (Array.isArray(setting.options)) {
const newOptions = []
for (const o of setting.options) {
newOptions.push({
value: o.value,
label: await this.pluginService.translateBy(this.npmName, o.label)
})
}
setting.options = newOptions
}
await this.pluginService.translateSetting(this.npmName, setting)
}
return settings
}
}

View File

@ -22,6 +22,7 @@ import {
import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms'
import { InstanceService } from '@app/shared/shared-instance'
import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main'
import { PluginInfo } from '@root-helpers/plugins-manager'
import {
HTMLServerConfig,
LiveVideo,
@ -37,6 +38,7 @@ import { VideoEditType } from './video-edit.type'
type VideoLanguages = VideoConstant<string> & { group?: string }
type PluginField = {
pluginInfo: PluginInfo
commonOptions: RegisterClientFormFieldOptions
videoFormOptions: RegisterClientVideoFieldOptions
}
@ -294,7 +296,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
})
}
private updatePluginFields () {
private async updatePluginFields () {
this.pluginFields = this.pluginService.getRegisteredVideoFormFields(this.type)
if (this.pluginFields.length === 0) return
@ -305,6 +307,8 @@ export class VideoEditComponent implements OnInit, OnDestroy {
const pluginDefaults: any = {}
for (const setting of this.pluginFields) {
await this.pluginService.translateSetting(setting.pluginInfo.plugin.npmName, setting.commonOptions)
const validator = (control: AbstractControl): ValidationErrors | null => {
if (!setting.commonOptions.error) return null

View File

@ -20,8 +20,8 @@ import {
PluginType,
PublicServerSetting,
RegisterClientFormFieldOptions,
RegisterClientSettingsScriptOptions,
RegisterClientRouteOptions,
RegisterClientSettingsScriptOptions,
RegisterClientVideoFieldOptions,
ServerConfigPlugin
} from '@shared/models'
@ -30,6 +30,7 @@ import { RegisterClientHelpers } from '../../../types/register-client-option.mod
type FormFields = {
video: {
pluginInfo: PluginInfo
commonOptions: RegisterClientFormFieldOptions
videoFormOptions: RegisterClientVideoFieldOptions
}[]
@ -44,8 +45,6 @@ export class PluginService implements ClientHook {
customModal: CustomModalComponent
private helpers: { [ npmName: string ]: RegisterClientHelpers } = {}
private formFields: FormFields = {
video: []
}
@ -134,27 +133,49 @@ export class PluginService implements ClientHook {
return Object.keys(this.clientRoutes)
}
translateBy (npmName: string, toTranslate: string) {
const helpers = this.helpers[npmName]
if (!helpers) {
console.error('Unknown helpers to translate %s from %s.', toTranslate, npmName)
return toTranslate
async translateSetting (npmName: string, setting: RegisterClientFormFieldOptions) {
for (const key of [ 'label', 'html', 'descriptionHTML' ]) {
if (setting[key]) setting[key] = await this.translateBy(npmName, setting[key])
}
return helpers.translate(toTranslate)
if (Array.isArray(setting.options)) {
const newOptions = []
for (const o of setting.options) {
newOptions.push({
value: o.value,
label: await this.translateBy(npmName, o.label)
})
}
setting.options = newOptions
}
}
private onFormFields (commonOptions: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) {
translateBy (npmName: string, toTranslate: string) {
const obs = this.translationsObservable
.pipe(
map(allTranslations => allTranslations[npmName]),
map(translations => peertubeTranslate(toTranslate, translations))
)
return firstValueFrom(obs)
}
private onFormFields (
pluginInfo: PluginInfo,
commonOptions: RegisterClientFormFieldOptions,
videoFormOptions: RegisterClientVideoFieldOptions
) {
this.formFields.video.push({
pluginInfo,
commonOptions,
videoFormOptions
})
}
private onSettingsScripts (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) {
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
this.settingsScripts[npmName] = options
this.settingsScripts[pluginInfo.plugin.npmName] = options
}
private onClientRoute (options: RegisterClientRouteOptions) {
@ -167,7 +188,7 @@ export class PluginService implements ClientHook {
private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers {
const { plugin } = pluginInfo
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
const npmName = pluginInfo.plugin.npmName
return {
getBaseStaticRoute: () => {
@ -241,11 +262,7 @@ export class PluginService implements ClientHook {
},
translate: (value: string) => {
const obs = this.translationsObservable
.pipe(map(allTranslations => allTranslations[npmName]))
.pipe(map(translations => peertubeTranslate(value, translations)))
return firstValueFrom(obs)
return this.translateBy(npmName, value)
}
}
}

View File

@ -37,8 +37,15 @@ type PluginInfo = {
}
type PeertubeHelpersFactory = (pluginInfo: PluginInfo) => RegisterClientHelpers
type OnFormFields = (options: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void
type OnFormFields = (
pluginInfo: PluginInfo,
options: RegisterClientFormFieldOptions,
videoFormOptions: RegisterClientVideoFieldOptions
) => void
type OnSettingsScripts = (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) => void
type OnClientRoute = (options: RegisterClientRouteOptions) => void
const logger = debug('peertube:plugins')
@ -223,7 +230,7 @@ class PluginsManager {
throw new Error('Video field registration is not supported')
}
return this.onFormFields(commonOptions, videoFormOptions)
return this.onFormFields(pluginInfo, commonOptions, videoFormOptions)
}
const registerSettingsScript = (options: RegisterClientSettingsScriptOptions) => {

View File

@ -3,6 +3,7 @@ import { CONFIG, isEmailEnabled } from '@server/initializers/config'
import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/lib/signup'
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
import { PluginModel } from '@server/models/server/plugin'
import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
import { Hooks } from './plugins/hooks'
import { PluginManager } from './plugins/plugin-manager'
@ -269,6 +270,7 @@ class ServerConfigManager {
getRegisteredThemes () {
return PluginManager.Instance.getRegisteredThemes()
.map(t => ({
npmName: PluginModel.buildNpmName(t.name, t.type),
name: t.name,
version: t.version,
description: t.description,
@ -280,6 +282,7 @@ class ServerConfigManager {
getRegisteredPlugins () {
return PluginManager.Instance.getRegisteredPlugins()
.map(p => ({
npmName: PluginModel.buildNpmName(p.name, p.type),
name: p.name,
version: p.version,
description: p.description,

View File

@ -99,9 +99,11 @@ describe('Test plugins', function () {
const theme = config.theme.registered.find(r => r.name === 'background-red')
expect(theme).to.not.be.undefined
expect(theme.npmName).to.equal('peertube-theme-background-red')
const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
expect(plugin).to.not.be.undefined
expect(plugin.npmName).to.equal('peertube-plugin-hello-world')
})
it('Should update the default theme in the configuration', async function () {

View File

@ -5,6 +5,7 @@ import { BroadcastMessageLevel } from './broadcast-message-level.type'
export interface ServerConfigPlugin {
name: string
npmName: string
version: string
description: string
clientScripts: { [name: string]: ClientScriptJSON }