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[]) { private async translateSettings (settings: RegisterServerSettingOptions[]) {
for (const setting of settings) { for (const setting of settings) {
for (const key of [ 'label', 'html', 'descriptionHTML' ]) { await this.pluginService.translateSetting(this.npmName, setting)
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
}
} }
return settings return settings
} }
} }

View File

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

View File

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

View File

@ -37,8 +37,15 @@ type PluginInfo = {
} }
type PeertubeHelpersFactory = (pluginInfo: PluginInfo) => RegisterClientHelpers 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 OnSettingsScripts = (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) => void
type OnClientRoute = (options: RegisterClientRouteOptions) => void type OnClientRoute = (options: RegisterClientRouteOptions) => void
const logger = debug('peertube:plugins') const logger = debug('peertube:plugins')
@ -223,7 +230,7 @@ class PluginsManager {
throw new Error('Video field registration is not supported') throw new Error('Video field registration is not supported')
} }
return this.onFormFields(commonOptions, videoFormOptions) return this.onFormFields(pluginInfo, commonOptions, videoFormOptions)
} }
const registerSettingsScript = (options: RegisterClientSettingsScriptOptions) => { 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 { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/lib/signup' import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/lib/signup'
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' 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 { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
import { Hooks } from './plugins/hooks' import { Hooks } from './plugins/hooks'
import { PluginManager } from './plugins/plugin-manager' import { PluginManager } from './plugins/plugin-manager'
@ -269,6 +270,7 @@ class ServerConfigManager {
getRegisteredThemes () { getRegisteredThemes () {
return PluginManager.Instance.getRegisteredThemes() return PluginManager.Instance.getRegisteredThemes()
.map(t => ({ .map(t => ({
npmName: PluginModel.buildNpmName(t.name, t.type),
name: t.name, name: t.name,
version: t.version, version: t.version,
description: t.description, description: t.description,
@ -280,6 +282,7 @@ class ServerConfigManager {
getRegisteredPlugins () { getRegisteredPlugins () {
return PluginManager.Instance.getRegisteredPlugins() return PluginManager.Instance.getRegisteredPlugins()
.map(p => ({ .map(p => ({
npmName: PluginModel.buildNpmName(p.name, p.type),
name: p.name, name: p.name,
version: p.version, version: p.version,
description: p.description, description: p.description,

View File

@ -99,9 +99,11 @@ describe('Test plugins', function () {
const theme = config.theme.registered.find(r => r.name === 'background-red') const theme = config.theme.registered.find(r => r.name === 'background-red')
expect(theme).to.not.be.undefined 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') const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
expect(plugin).to.not.be.undefined 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 () { 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 { export interface ServerConfigPlugin {
name: string name: string
npmName: string
version: string version: string
description: string description: string
clientScripts: { [name: string]: ClientScriptJSON } clientScripts: { [name: string]: ClientScriptJSON }