From 9d18e401a747fa08d642859c1f031101f580e4ce Mon Sep 17 00:00:00 2001 From: John Livingston <38844060+JohnXLivingston@users.noreply.github.com> Date: Wed, 15 Feb 2023 11:54:48 +0100 Subject: [PATCH] Implements #153: Settings translations (#155) Implementing a new translating system, so we can more easily translate settings strings. Indeed, these strings are difficult to embed in JSON format. We still use JSON files for standard strings, but in addition we have dedicated YAML files to translate settings strings. There is a new build-languages.js script that merge all translations in JSON files. Other modifications: * Eslint: ignoring documentation and build scripts. * french settings translations. --- .eslintrc.json | 7 +- CHANGELOG.md | 4 + build-languages.js | 154 +++++++++++ client/admin-plugin-client-plugin.ts | 13 +- languages/ca.json | 8 +- languages/de.json | 8 +- languages/eo.json | 8 +- languages/es.json | 8 +- languages/eu.json | 8 +- languages/fr.json | 8 +- languages/it.json | 8 +- languages/ja.json | 8 +- languages/oc.json | 8 +- languages/pl.json | 8 +- languages/settings/en.yml | 186 +++++++++++++ languages/settings/fr.yml | 204 ++++++++++++++ package-lock.json | 34 ++- package.json | 24 +- server/lib/settings.ts | 255 ++++++++---------- .../contributing/translate/_index.en.md | 34 +++ .../contributing/translate/_index.fr.md | 44 +++ 21 files changed, 857 insertions(+), 182 deletions(-) create mode 100644 build-languages.js create mode 100644 languages/settings/en.yml create mode 100644 languages/settings/fr.yml diff --git a/.eslintrc.json b/.eslintrc.json index 40ad1516..b6a9a159 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,6 +4,11 @@ "extends": [], "globals": {}, "plugins": [], - "ignorePatterns": ["node_modules/", "dist/", "webpack.config.js", "build/", "vendor/"], + "ignorePatterns": [ + "node_modules/", "dist/", "webpack.config.js", + "build/", + "vendor/", + "support/documentation", + "build-*js"], "rules": {} } diff --git a/CHANGELOG.md b/CHANGELOG.md index d86aa0ab..07460231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## ??? (Not Released Yet) +### New Features + +* Settings page translations. For now: english and french are available. + ### Minor changes and fixes * Updating a link to the documentation in the settings page. diff --git a/build-languages.js b/build-languages.js new file mode 100644 index 00000000..21991364 --- /dev/null +++ b/build-languages.js @@ -0,0 +1,154 @@ +/** + * This script is used to build the translations files. + * + * Indeed, some strings used in plugin settings are not easy to write + * in JSON format (contains html, double quotes, line breaks, ...). + * So we use YAML files to translates these strings, + * including the english version. + * + * This scripts takes the standard JSON files, the YAML translation files, + * and mixes everything up in dist/languages/xx.json. + */ +const fs = require('fs') +const path = require('path') +const YAML = require('yaml') + +class BuildLanguages { + destinationDir = null + langs = [] + translationsStrings = {} + monoLingualReferences = {} + + constructor () { + this.destinationDir = path.resolve(__dirname, 'dist', 'languages') + } + + async generateFiles () { + await this.loadLangs() + await this.initTranslationStrings() + await this.readJSONTranslations() + await this.readSettingsTranslations() + + await this.ensureDestinationDir() + await this.writeJSONTranslations() + await this.writeMonoLingualReferences() + } + + loadLangs () { + const packagejson = require('./package.json') + const translations = packagejson.translations || {} + this.langs = Object.values(translations).map(filename => { + return filename.match(/^.*\/(\w+)\.json$/)[1] + }) + console.log('Existings languages: ', this.langs) + } + + initTranslationStrings () { + console.log('Initializing translations strings...') + const translationsStrings = {} + for (const l of this.langs) { + translationsStrings[l] = {} + } + this.translationsStrings = translationsStrings + } + + async readJSONTranslations () { + console.log('Reading standard JSON translation strings...') + const translationsStrings = this.translationsStrings + for (const l of this.langs) { + const filePath = path.resolve(__dirname, 'languages', l + '.json') + if (!fs.existsSync(filePath)) { + console.warn(`File ${filePath} missing, ignoring.`) + continue + } + const t = require(filePath) + for (const k in t) { + const v = t[k] + if (k in translationsStrings[l]) { + throw new Error(`Duplicate translation for key ${k} in lang ${l}.`) + } + translationsStrings[l][k] = v + } + } + } + + async readSettingsTranslations () { + console.log('Reading Settings Yaml translation strings...') + + // First we must get the english reference file, + // that will give us the keys to use in final JSON. + + const reference = await this.getYmlFileContent(path.resolve(__dirname, 'languages', 'settings', 'en.yml')) + this.monoLingualReferences['settings'] = reference + + const translationsStrings = this.translationsStrings + for (const l of this.langs) { + const filePath = path.resolve(__dirname, 'languages', 'settings', l + '.yml') + const o = await this.getYmlFileContent(filePath) + + for (const k in o) { + if (!(k in reference)) { + throw new Error(`File ${filePath} contains unknown keys. Key=${k}.`) + } + const newKey = reference[k] + this.translationsStrings[l][newKey] = o[k] + } + } + } + + async getYmlFileContent (filePath) { + if (!fs.existsSync(filePath)) { + console.warn(`File ${filePath} missing, ignoring.`) + return {} + } + + const content = await fs.promises.readFile(filePath, 'utf8') + const o = YAML.parse(content) || {} + for (const k in o) { + let v = o[k] + if (v === null) { + // this value is ok! + continue + } + if ((typeof v) !== 'string') { + throw new Error(`File ${filePath} contains strings that are not strings! Key=${k}`) + } + + // We are normalizing the string, to avoid problems. + // As it is supposed to be html, we will strip newlines and multiple adjacent spaces. + v = v.replace(/\n/g, ' ') + v = v.replace(/\s\s+/g, ' ') + v = v.trim() + o[k] = v + } + return o + } + + async ensureDestinationDir () { + if (!fs.existsSync(this.destinationDir)) { + await fs.promises.mkdir(this.destinationDir) + } + } + + async writeJSONTranslations () { + console.log('Writing JSON files...') + for (const l of this.langs) { + const filePath = path.resolve(this.destinationDir, l + '.json') + await fs.promises.writeFile(filePath, JSON.stringify(this.translationsStrings[l])) + } + } + + async writeMonoLingualReferences () { + console.log('Writing JSON reference files...') + for (const name in this.monoLingualReferences) { + const filePath = path.resolve(this.destinationDir, name + '.reference.json') + await fs.promises.writeFile(filePath, JSON.stringify(this.monoLingualReferences[name])) + } + } +} + +const bl = new BuildLanguages() +bl.generateFiles().then(() => {}, (err) => { + console.error(err) + throw err +}) diff --git a/client/admin-plugin-client-plugin.ts b/client/admin-plugin-client-plugin.ts index e74cc51d..6dcc4bde 100644 --- a/client/admin-plugin-client-plugin.ts +++ b/client/admin-plugin-client-plugin.ts @@ -99,14 +99,13 @@ function register ({ registerHook, registerSettingsScript, peertubeHelpers }: Re const table = document.createElement('table') table.classList.add('peertube-plugin-livechat-prosody-list-rooms') container.append(table) - // TODO: translate labels. const labels: any = { - RoomName: 'Room name', - RoomDescription: 'Room description', - NotFound: 'Not found', - Video: 'Video', - Channel: 'Channel', - LastActivity: 'Last activity' + RoomName: await peertubeHelpers.translate('Room name'), + RoomDescription: await peertubeHelpers.translate('Room description'), + NotFound: await peertubeHelpers.translate('Not found'), + Video: await peertubeHelpers.translate('Video'), + Channel: await peertubeHelpers.translate('Channel'), + LastActivity: await peertubeHelpers.translate('Last activity') } const titleLineEl = document.createElement('tr') diff --git a/languages/ca.json b/languages/ca.json index a27a0379..0e168c55 100644 --- a/languages/ca.json +++ b/languages/ca.json @@ -15,5 +15,11 @@ "Open": false, "Use current theme colors": false, "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/de.json b/languages/de.json index 8d3e5580..f9dd09a2 100644 --- a/languages/de.json +++ b/languages/de.json @@ -15,5 +15,11 @@ "Open": "Öffnen", "Use current theme colors": "Die derzeitigen Themenfarben nutzen", "Generate an iframe to embed the chat in a website": "IFrame-Element erstellen, um den Chat in eine Webseite zu integrieren", - "Chat for live stream": "Chat für den Livestream" + "Chat for live stream": "Chat für den Livestream", + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/eo.json b/languages/eo.json index 98c4c540..50d043d8 100644 --- a/languages/eo.json +++ b/languages/eo.json @@ -15,5 +15,11 @@ "Open": "Malfermi", "Use current theme colors": "Uzi koloroj el la nuna etoso", "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/es.json b/languages/es.json index 9ed3bf5b..a59723fd 100644 --- a/languages/es.json +++ b/languages/es.json @@ -15,5 +15,11 @@ "Open": "Abrir", "Use current theme colors": "Utilizar los colores del tema actual", "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/eu.json b/languages/eu.json index b275b0f6..e1e84e47 100644 --- a/languages/eu.json +++ b/languages/eu.json @@ -15,5 +15,11 @@ "Open": "Ireki", "Use current theme colors": "Erabili uneko itxuraren koloreak", "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/fr.json b/languages/fr.json index af3c565e..99bee396 100644 --- a/languages/fr.json +++ b/languages/fr.json @@ -15,5 +15,11 @@ "Open": "Ouvrir", "Use current theme colors": "Utiliser les couleurs du thème courant", "Generate an iframe to embed the chat in a website": "Générer une iframe pour intégrer le tchat dans un site web", - "Chat for live stream:": "Tchat pour le direct :" + "Chat for live stream:": "Tchat pour le direct :", + "Room name": "Nom du salon", + "Room description": "Description du salon", + "Not found": "Non trouvé", + "Video": "Vidéo", + "Channel": "Chaîne", + "Last activity": "Dernière activité" } diff --git a/languages/it.json b/languages/it.json index 46389476..7e7173bf 100644 --- a/languages/it.json +++ b/languages/it.json @@ -15,5 +15,11 @@ "Open": false, "Use current theme colors": false, "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/ja.json b/languages/ja.json index 785f64ca..cd9edf38 100644 --- a/languages/ja.json +++ b/languages/ja.json @@ -15,5 +15,11 @@ "Open": "開く", "Use current theme colors": "現在のテーマカラーを使用する", "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/oc.json b/languages/oc.json index 206b74a5..e50d2e31 100644 --- a/languages/oc.json +++ b/languages/oc.json @@ -15,5 +15,11 @@ "Open": "Dobrir", "Use current theme colors": "Utilizar las colors del tèma actual" , "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/pl.json b/languages/pl.json index 08f4b369..0261be87 100644 --- a/languages/pl.json +++ b/languages/pl.json @@ -15,5 +15,11 @@ "Open": false, "Use current theme colors": false, "Generate an iframe to embed the chat in a website": false, - "Chat for live stream": false + "Chat for live stream": false, + "Room name": false, + "Room description": false, + "Not found": false, + "Video": false, + "Channel": false, + "Last activity": false } diff --git a/languages/settings/en.yml b/languages/settings/en.yml new file mode 100644 index 00000000..d46c0482 --- /dev/null +++ b/languages/settings/en.yml @@ -0,0 +1,186 @@ +important_note_title: "

Important notes

" +important_note_text: | + You can find the plugin documentation here: + + Peertube Plugin Livechat documentation + . + +diagnostic: | + Before asking for help, please use the diagnostic tool: + Launch diagnostic + (if this button is not opening a new window, please try to refresh the page). + +chat_title: "

Chat

" + +list_rooms_label: "List existing rooms" +list_rooms_description: | + List rooms + +chat_behaviour_description: "

Chat behaviour

" + +room_type_label: "Room type" +room_type_description: "You can choose here to have separate rooms for each video, or to group them by channel." +room_type_option_video: "Each video has its own webchat room" +room_type_option_channel: "Webchat rooms are grouped by channel" + +auto_display_label: "Automatically open the chat" +auto_display_description: "When watching a video, the chatbox will automatically open." + +open_blank_label: "Show the «open in new window» button" +open_blank_description: "There will be a button for opening the web chat in a new window." + +share_url_label: "Show the «share chat link» button" +share_url_description: "There will be a button for sharing a chat url (could be used to intregrated in OBS for example)." +share_url_option_nobody: "Show for nobody" +share_url_option_everyone: "Show for everyone" +share_url_option_owner: "Show for the video owner" +share_url_option_owner_moderators: "Show for the video owner and instance's moderators" + +per_live_video_label: "Users can activate the chat for their lives" +per_live_video_description: "If checked, all live videos will have a checkbox in their properties for enabling the web chat." + +per_live_video_warning_description: | + + You have enabled the setting «Users can activate the chat for their lives». + It is redundant with the «Activate chat for all lives» setting. + + +all_lives_label: "Activate chat for all lives" +all_lives_description: "If checked, the chat will be enabled for all lives." + +all_non_lives_label: "Activate chat for all non-lives" +all_non_lives_description: "If checked, the chat will be enable for all video that are not lives." + +videos_list_label: "Activate chat for these videos" +videos_list_description: | + Videos UUIDs for which we want a web chat. + Can be non-live videos. One per line.
+ You can add comments: everything after the # character will be stripped off, and empty lines ignored.
+ Don't add private videos, the UUIDs will be send to frontend. + +no_anonymous_label: "Hide the chat for anonymous users" +no_anonymous_description: "If checked, anonymous Peertube users won't see the chat." + +theming_advanced_description: "

Theming

" + +converse_theme_label: "ConverseJS theme" +converse_theme_description: "Please choose the converseJS theme you want to use." +converse_theme_option_peertube: "Peertube theme" +converse_theme_option_default: "Default ConverseJS theme" +converse_theme_option_concord: "ConverseJS concord theme" + +autocolors_label: "Automatic color detection" +autocolors_description: | + Try to auto detect colors from user's current theme.
+ When this settings is enabled, the plugin tries to auto-detect colors to apply to the chat theme.
+ If this is not correctly working for some of your Peertube theme, you can disable this option. + You can report the bug on the official + + issue tracker + . Don't forget to specify which theme is not working.` + +chat_style_label: "Webchat iframe style attribute" +chat_style_description: | + Additional styles to be added on the iframe style attribute.
+ Example: height:400px; + +prosody_advanced_description: "

Chat server advanced settings

" + +help_builtin_prosody_label: "Prosody server" +help_builtin_prosody_description: | + This plugin uses the Prosody XMPP server to handle chat rooms.
+ This plugin comes with a Prosody AppImage, that will be used to run the service. + +system_prosody_label: "Use system Prosody" +system_prosody_description: | + Warning: don't check this settings if you are not sure of what you are doing.
+ By checking this settings, your Peertube will use the Prosody server that comes with your system, + and not the embeded AppImage.
+ Only use this if you encounter problems with the embedded Prosody. + +disable_websocket_label: "Disable Websocket" +disable_websocket_description: | + With Peertube >= 5.0.0, this plugin try to use Websocket connection for chatting. + If the user's browser or connection is not compatible, the browser will automatically fallback on the BOSH protocol. +
+ But in rare case, this can fail. For example if you have a reverse proxy in front of Peertube that does not + allow Websocket connection for plugins. + In this case, you can check this settings to disable Websocket connections. + +prosody_port_label: "Prosody port" +prosody_port_description: | + The port that will be used by the Prosody server.
+ Change it if this port is already in use on your server.
+ You can close this port on your firewall, it will not be accessed from the outer world.
+ Note: this might change in a near feature, as it is planned to add feature to activate external connections. + +prosody_peertube_uri_label: "Peertube url for API calls" +prosody_peertube_uri_description: | + Please let this settings empty if you don't know what you are doing.
+ In some rare case, Prosody can't call Peertube's API from its public URI. + You can use this field to customise Peertube's URI for Prosody modules + (for example with «http://localhost:9000» or «http://127.0.0.1:9000»). + +prosody_muc_log_by_default_label: "Log rooms content by default" +prosody_muc_log_by_default_description: | + If checked, room contents will be saved by default. + Any user that join a room will see what was written before he joins.
+ Please note that it is always possible to enable/disable the content + archiving for a specific room, by editing its properties. + +prosody_muc_expiration_label: "Room logs expiration" +prosody_muc_expiration_description: | + You can choose here how long the chatting room's content is kept by the server. The value can be: + + +prosody_c2s_label: "Enable client to server connections" +prosody_c2s_description: | + Enable XMPP clients to connect to the builtin Prosody server.
+ This option alone only allows connections from localhost clients. + +prosody_c2s_port_label: "Prosody client to server port" +prosody_c2s_port_description: | + The port that will be used by the c2s module of the builtin Prosody server.
+ XMPP clients shall use this port to connect.
+ Change it if this port is already in use on your server.
+ You can keep this port closed on your firewall for now, it will not be accessed from the outer world.
+ Note: this might change in a near feature, as it is planned to add feature to activate external connections. + +prosody_components_label: "Enable custom Prosody external components" +prosody_components_description: | + Enable the use of external XMPP components.
+ This option alone only allows connections from localhost.
+ This feature can for example be used to connect some bots to the chatting rooms. + +prosody_components_port_label: "Prosody external components port" +prosody_components_port_description: | + The port that will be used by XMPP components to connect to the Prosody server.
+ Change it if this port is already in use on your server.
+ You can keep this port closed on your firewall for now, it will not be accessed from the outer world.
+ Note: this might change in a near feature, as it is planned to add feature to activate external connections. + +prosody_components_list_label: "External components" +prosody_components_list_description: | + The external components to declare: + diff --git a/languages/settings/fr.yml b/languages/settings/fr.yml new file mode 100644 index 00000000..9979cbc1 --- /dev/null +++ b/languages/settings/fr.yml @@ -0,0 +1,204 @@ +important_note_title: "

Note importante

" +important_note_text: | + Vous pouvez trouver la documentation du plugin ici: + + Documentation du Plugin Peertube Livechat + . + +diagnostic: | + Avant de demander de l'aide, merci d'utiliser l'outils de diagnostic: + Lancer le diagnostique + (si ce bouton n'ouvre pas une nouvelle fenêtre, merci d'essayer de raffraichir la page). + +chat_title: "

Tchat

" + +list_rooms_label: "Lister les salons de tchat existants" +list_rooms_description: | + Lister les salons + +chat_behaviour_description: "

Comportement du tchat

" + +room_type_label: "Type de salon" +room_type_description: "Vous pouvez choisir d'avoir des salons séparés pour chaque vidéo, ou de les grouper par chaîne." +room_type_option_video: "Chaque video a son propre salon de discussion" +room_type_option_channel: "Les salons sont regroupés par chaîne" + +auto_display_label: "Ouvrir automatiquement le tchat" +auto_display_description: "Quand on regarde une vidéo, le tchat va s'ouvrir automatiquement." + +open_blank_label: "Montrer le bouton «ouvrir dans une nouvelle fenêtre»" +open_blank_description: "Il y aura un bouton pour ouvrir le tchat dans une nouvelle fenêtre." + +share_url_label: "Montrer le bouton «partager le lien du salon»" +share_url_description: "Il y aura un bouton permettant de partager le lien vers le tchat (peut par exemple être utilisé pour l'intégration dans OBS)." +share_url_option_nobody: "Ne pas le montrer" +share_url_option_everyone: "Le montrer à tout le monde" +share_url_option_owner: "Le montrer au proriétaire de la vidéo" +share_url_option_owner_moderators: "Le montrer au propriétaire de la vidéo, et aux modérateur⋅rices de l'instance" + +per_live_video_label: "Les utilisateur⋅rices peuvent activer le tchat pour leurs directs" +per_live_video_description: "Si coché, il y aura pour tous les directs une case à cocher dans les propriétés qui permettra d'activer/désactiver le tchat." + +per_live_video_warning_description: | + + Vous avez activé le paramètre «Les utilisateur⋅rices peuvent activer le tchat pour leurs directs». + C'est redondant avec «Activer le tchat pour tous les directs». + + +all_lives_label: "Activer le tchat pour tous les directs" +all_lives_description: "Si coché, il y aura un tchat pour tous les directs." + +all_non_lives_label: "Activer le tchat pour toutes les vidéos «non-direct»" +all_non_lives_description: "Si coché, il y aura un tchat pour toutes les vidéos qui ne sont pas des directs." + +videos_list_label: "Activer le tchat pour ces vidéos" +videos_list_description: | + Mettez ici les UUIDs des vidéos pour lequelles vous voulez forcer l'activation + du tchat. + Cela peut être des directs, ou non. + Un UUID par ligne.
+ Vous pouvez ajouter des commentaires: tout ce qui se trouve après le caractère # + sera retiré, et les lignes vides ignorées.
+ N'ajoutez pas de vidéos privées, les UUIDs fuiteraient. + +no_anonymous_label: "Masque les tchats pour les utilisateur⋅rices anonymes" +no_anonymous_description: "Si coché, les utilisteur⋅rices non connecté⋅es ne verront pas les tchats." + +theming_advanced_description: "

Personnalisation des thèmes

" + +converse_theme_label: "Thème ConverseJS" +converse_theme_description: "Merci de choisir le thème ConverseJS que vous voulez utiliser." +converse_theme_option_peertube: "Thème Peertube" +converse_theme_option_default: "Thème par défaut de ConverseJS" +converse_theme_option_concord: "Thème concord de ConverseJS" + +autocolors_label: "Détection automatique des couleurs" +autocolors_description: | + Essaie de détecter automatiquement les couleurs du thème courant de l'utilisateur⋅rice. +
+ Quand ce paramètre est activé, le plugin essaie de détecter automatiquement les + couleurs à appliquer au thème du tchat. +
+ Si cela ne fonctionne pas correctement pour certains de vos thèmes Peertube, + vous pouvez désactiver cette option. + Vous pouvez rapporter les bugs sur le + gestionnaire de ticket + . N'oubliez pas de préciser pour quel thème cela ne fonctionne pas. + +chat_style_label: "Attribut de style de l'iframe du tchat" +chat_style_description: | + Styles additionnels à appliquer sur l'iframe du tchat.
+ Exemple: height:400px; + +prosody_advanced_description: "

Paramètres avancés du serveur de tchat

" + +help_builtin_prosody_label: "Serveur Prosody" +help_builtin_prosody_description: | + Ce plugin utilise le serveur XMPP Prosody pour gérer les salons de discussion.
+ Ce plugin inclu une AppImage de Prosody, qui va être utilisée pour faire tourner le service. + +system_prosody_label: "Utiliser le serveur Prosody installé sur le système" +system_prosody_description: | + Attention: ne cocher pas ce paramètre si vous n'êtes pas sûr de ce que vous faites.
+ En cochant ce paramètre, Peertube va utiliser l'exécutable Prosody fourni + par le système, et non l'AppImage intégrée.
+ N'utiliser cette option que si vous rencontrez des problèmes pour utiliser l'AppImage intégrée. + +disable_websocket_label: "Désactiver Websocket" +disable_websocket_description: | + Avec Peertube >= 5.0.0, ce plugin va essayer d'utiliser Websocket pour les connections au tchat. + Si le navigateur de l'utilisateur⋅rice ou sa connection n'est pas compatible, le navigateur va + automatiquement passer au protocole BOSH. +
+ Mais dans de rare cas, ça pourrait échouer. Par exemple si vous avez un reverse proxy devant votre Peertube + qui ne permettrait pas les connection Websocket. + Dans ce cas, vous pouvez cocher cette option pour désactiver les connections Websocket. + +prosody_port_label: "Port Prosody" +prosody_port_description: | + Le port qui va être utilisé par le serveur Prosody.
+ Changer le si ce port est déjà utilisé sur votre serveur.
+ Vous pouvez fermer ce port sur votre pare-feu, il ne sera pas accéder par le monde extérieur.
+ Note: cela pourrait changer dans un futur proche, car il est prévu d'ajouter des paramètres pour autoriser les connections externes. + +prosody_peertube_uri_label: "Url Peertube pour les appels d'API" +prosody_peertube_uri_description: | + Merci de ne pas toucher à ce paramètre si vous ne savez pas ce que vous faites.
+ Dans de rare cas, le serveur Prosody ne peut appeler l'API de Peertube en utilisant l'url publique. + Vous pouvez utiliser ce paramètre pour personnaliser l'url que les modules Prosody utiliseront pour + les API Peertube (par exemple en mettant «http://localhost:9000» ou «http://127.0.0.1:9000»). + +prosody_muc_log_by_default_label: "Enregistrer les salons par défaut" +prosody_muc_log_by_default_description: | + Si coché, le contenu des salons sera enregistré par défaut. + Quand un⋅e utilisateur⋅rice rejoint un salon, iel pourra voir ce qui a été dit avant. +
+ À noter qu'il est toujours possible d'activer/désactiver cette fonctionnalité + pour un salon spécifique, en changeant ses paramètres. + + +prosody_muc_expiration_label: "Expiration des journaux de salon" +prosody_muc_expiration_description: | + Vous pouvez choisir combien de temps le contenu des salons est gardé sur le serveur. + La valeur peut être: + + +prosody_c2s_label: "Activer les connections client vers serveur" +prosody_c2s_description: | + Autoriser les clients XMPP à se connecter au serveur Prosody.
+ Cette option seule n'autorise que les connections de clients sur le localhost. + +prosody_c2s_port_label: "Port Prosody client vers serveur" +prosody_c2s_port_description: | + Le port à utiliser pour les connections XMPP c2s (client to server).
+ Les clients XMPP devront utiliser ce port pour se connecter.
+ Changez ce port si le port est déjà utilisé sur votre serveur.
+ Pour l'instant, vous pouvez garder ce port fermé sur votre pare-feu, + il ne sera pas accessible du monde extérieur (Prosody n'écoute que sur localhost).
+ Note: cela pourrait changer dans un futur proche, car il est prévu d'ajouter des paramètres pour autoriser les connections externes. + +prosody_components_label: "Activer les composants externe personnalisés Prosody" +prosody_components_description: | + Active l'utilisation des «External XMPP components».
+ Cette option seule n'autorise que les connections depuis localhost.
+ Cette fonctionnalité peut par exemple être utilisée pour connecter des bots aux salons. + +prosody_components_port_label: "Port pour les composants externe Prosody" +prosody_components_port_description: | + Le port à utiliser pour les XMPP components.
+ Changez ce port s'il est déjà utilisé sur votre serveur.
+ Pour l'instant, vous pouvez garder ce port fermé sur votre pare-feu, + il ne sera pas accessible du monde extérieur (Prosody n'écoute que sur localhost).
+ Note: cela pourrait changer dans un futur proche, car il est prévu d'ajouter des paramètres pour autoriser les connections externes. + +prosody_components_list_label: "Composants externes" +prosody_components_list_description: | + Les composants externes à déclarer : + diff --git a/package-lock.json b/package-lock.json index c56c2bd4..e11823bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,8 @@ "stylelint-config-recommended-scss": "^5.0.1", "stylelint-config-standard-scss": "^2.0.1", "svgo": "^2.8.0", - "typescript": "^4.3.5" + "typescript": "^4.3.5", + "yaml": "^2.2.1" }, "engines": { "npm": ">=7" @@ -4690,6 +4691,15 @@ "node": ">=10" } }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/cron-parser": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.7.0.tgz", @@ -11504,12 +11514,12 @@ "dev": true }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", + "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", "dev": true, "engines": { - "node": ">= 6" + "node": ">= 14" } } }, @@ -15332,6 +15342,14 @@ "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" + }, + "dependencies": { + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + } } }, "cron-parser": { @@ -20483,9 +20501,9 @@ "dev": true }, "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", + "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", "dev": true } } diff --git a/package.json b/package.json index 42fd8b36..8d7095b0 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,8 @@ "stylelint-config-recommended-scss": "^5.0.1", "stylelint-config-standard-scss": "^2.0.1", "svgo": "^2.8.0", - "typescript": "^4.3.5" + "typescript": "^4.3.5", + "yaml": "^2.2.1" }, "engine": { "peertube": ">=4.2.0" @@ -94,7 +95,8 @@ "build:serverconverse": "mkdir -p dist/server/conversejs && cp conversejs/index.html dist/server/conversejs/", "build:prosodymodules": "mkdir -p dist/server/prosody-modules && cp -r prosody-modules/* dist/server/prosody-modules/", "build:styles": "sass assets/styles:dist/assets/styles", - "build": "npm-run-all -s clean:light check:client:tsc -p build:converse build:prosody build:images build:avatars build:client build:server build:serverconverse build:prosodymodules build:styles", + "build:languages": "node ./build-languages.js", + "build": "npm-run-all -s clean:light check:client:tsc -p build:converse build:prosody build:images build:avatars build:client build:server build:languages build:serverconverse build:prosodymodules build:styles", "lint": "npm-run-all -s lint:script lint:styles", "lint:script": "npx eslint --ext .js --ext .ts .", "lint:styles": "stylelint 'conversejs/**/*.scss' 'assets/styles/**/*.css'", @@ -108,14 +110,14 @@ "settings": "dist/client/settings" }, "translations": { - "ca-ES": "./languages/ca.json", - "fr-FR": "./languages/fr.json", - "eo": "./languages/eo.json", - "eu-ES": "./languages/eu.json", - "oc": "./languages/oc.json", - "pl-PL": "./languages/pl.json", - "de-DE": "./languages/de.json", - "it-IT": "./languages/it.json", - "ja-JP": "./languages/ja.json" + "ca-ES": "./dist/languages/ca.json", + "fr-FR": "./dist/languages/fr.json", + "eo": "./dist/languages/eo.json", + "eu-ES": "./dist/languages/eu.json", + "oc": "./dist/languages/oc.json", + "pl-PL": "./dist/languages/pl.json", + "de-DE": "./dist/languages/de.json", + "it-IT": "./dist/languages/it.json", + "ja-JP": "./dist/languages/ja.json" } } diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 72615a28..0620be40 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -1,30 +1,65 @@ import type { RegisterServerOptions } from '@peertube/peertube-types' import { ensureProsodyRunning } from './prosody/ctl' import type { ConverseJSTheme } from '../../shared/lib/types' +import { existsSync, promises as fsPromises } from 'fs' +import { resolve } from 'path' -function initSettings (options: RegisterServerOptions): void { +const locContent: Map = new Map() + +/** + * Currently, the Peertube plugin system assumes that settings strings + * are localized in english, and will be translated on front-end. + * This system make it hard to have complex strings (with html, newlines, ...). + * See https://github.com/Chocobozzz/PeerTube/issues/4523 + * + * Waiting for a better solution, we implemented a custom solution: + * - We are using keys to identify setting strings + * - the `loc` function gets the english segment for the key + * - the build-languages.js script builds all needed files. + * @param key The key to translate + */ +function loc (key: string): string { + return locContent.get(key) ?? key +} + +async function loadLoc (): Promise { + const filePath = resolve(__dirname, '..', '..', 'languages', 'settings.reference.json') + if (!existsSync(filePath)) { + throw new Error(`File ${filePath} missing, can't load plugin settings`) + } + const content = await fsPromises.readFile(filePath, 'utf8') + const json = JSON.parse(content ?? '{}') + if (typeof json !== 'object') { + throw new Error(`File ${filePath} invalid, can't load plugin settings`) + } + for (const k in json) { + const v = json[k] + if (typeof v === 'string') { + locContent.set(k, v) + } + } +} + +async function initSettings (options: RegisterServerOptions): Promise { const { peertubeHelpers, registerSetting, settingsManager } = options + await loadLoc() + // ********** IMPORTANT NOTES registerSetting({ type: 'html', private: true, - descriptionHTML: '

Important notes

' + descriptionHTML: loc('important_note_title') }) registerSetting({ type: 'html', private: true, - descriptionHTML: `You can find the plugin documentation here: - - Peertube Plugin Livechat documentation -.` + descriptionHTML: loc('important_note_text') }) registerSetting({ type: 'html', private: true, - descriptionHTML: `Before asking for help, please use the diagnostic tool: -Launch diagnostic -(if this button is not opening a new window, please try to refresh the page).` + descriptionHTML: loc('diagnostic') }) if (process.arch !== 'x64' && process.arch !== 'x86_64') { @@ -32,6 +67,8 @@ function initSettings (options: RegisterServerOptions): void { name: 'prosody-arch-warning', type: 'html', private: true, + // Note: the following text as a variable in it. + // Not translating it: it should be very rare. descriptionHTML: ` It seems that your are using a ${process.arch} CPU, which is not compatible with the plugin. @@ -50,13 +87,13 @@ Please read registerSetting({ type: 'html', private: true, - descriptionHTML: '

Chat

' + descriptionHTML: loc('chat_title') }) registerSetting({ name: 'prosody-list-rooms', - label: 'List existing rooms', + label: loc('list_rooms_label'), type: 'html', - descriptionHTML: 'List rooms', + descriptionHTML: loc('list_rooms_description'), private: true }) @@ -64,102 +101,94 @@ Please read registerSetting({ type: 'html', private: true, - descriptionHTML: '

Chat behaviour

' + descriptionHTML: loc('chat_behaviour_description') }) registerSetting({ name: 'prosody-room-type', - label: 'Room type', + label: loc('room_type_label'), type: 'select', - descriptionHTML: 'You can choose here to have separate rooms for each video, or to group them by channel.', + descriptionHTML: loc('room_type_description'), private: false, default: 'video', options: [ - { value: 'video', label: 'Each video has its own webchat room' }, - { value: 'channel', label: 'Webchat rooms are grouped by channel' } + { value: 'video', label: loc('room_type_option_video') }, + { value: 'channel', label: loc('room_type_option_channel') } ] }) registerSetting({ name: 'chat-auto-display', - label: 'Automatically open the chat', - descriptionHTML: 'When watching a video, the chatbox will automatically open', + label: loc('auto_display_label'), + descriptionHTML: loc('auto_display_description'), type: 'input-checkbox', default: true, private: false }) registerSetting({ name: 'chat-open-blank', - label: 'Show the «open in new window» button', - descriptionHTML: 'There will be a button for opening the web chat in a new window.', + label: loc('open_blank_label'), + descriptionHTML: loc('open_blank_description'), private: false, type: 'input-checkbox', default: true }) registerSetting({ name: 'chat-share-url', - label: 'Show the «share chat link» button', - descriptionHTML: 'There will be a button for sharing a chat url (could be used to intregrated in OBS for example).', + label: loc('share_url_label'), + descriptionHTML: loc('share_url_description'), private: false, type: 'select', default: 'owner', options: [ - { label: 'Show for nobody', value: 'nobody' }, - { label: 'Show for everyone', value: 'everyone' }, - { label: 'Show for the video owner', value: 'owner' }, - { label: 'Show for the video owner and instance\'s moderators', value: 'owner+moderators' } + { value: 'nobody', label: loc('share_url_option_nobody') }, + { value: 'everyone', label: loc('share_url_option_everyone') }, + { value: 'owner', label: loc('share_url_option_owner') }, + { value: 'owner+moderators', label: loc('share_url_option_owner_moderators') } ] }) registerSetting({ name: 'chat-per-live-video', - label: 'Users can activate the chat for their lives', + label: loc('per_live_video_label'), type: 'input-checkbox', default: true, - descriptionHTML: 'If checked, all live videos will have a checkbox in their properties for enabling the web chat.', + descriptionHTML: loc('per_live_video_description'), private: false }) registerSetting({ name: 'chat-per-live-video-warning', type: 'html', private: true, - descriptionHTML: -` - You have enabled the setting «Users can activate the chat for their lives». - It is redundant with the «Activate chat for all lives» setting. -` + descriptionHTML: loc('per_live_video_warning_description') }) registerSetting({ name: 'chat-all-lives', - label: 'Activate chat for all lives', + label: loc('all_lives_label'), type: 'input-checkbox', default: false, - descriptionHTML: 'If checked, the chat will be enabled for all lives.', + descriptionHTML: loc('all_lives_description'), private: false }) registerSetting({ name: 'chat-all-non-lives', - label: 'Activate chat for all non-lives', + label: loc('all_non_lives_label'), type: 'input-checkbox', default: false, - descriptionHTML: 'If checked, the chat will be enable for all video that are not lives.', + descriptionHTML: loc('all_non_lives_description'), private: false }) registerSetting({ name: 'chat-videos-list', - label: 'Activate chat for these videos', + label: loc('videos_list_label'), type: 'input-textarea', default: '', - descriptionHTML: -`Videos UUIDs for which we want a web chat. -Can be non-live videos. One per line.
-You can add comments: everything after the # character will be stripped off, and empty lines ignored.
-Don't add private videos, the UUIDs will be send to frontend.`, + descriptionHTML: loc('videos_list_description'), private: false }) registerSetting({ name: 'chat-no-anonymous', - label: 'Hide the chat for anonymous users', + label: loc('no_anonymous_label'), type: 'input-checkbox', default: false, - descriptionHTML: 'If checked, anonymous Peertube users won\'t see the chat.', + descriptionHTML: loc('no_anonymous_description'), private: false }) @@ -168,47 +197,38 @@ Don't add private videos, the UUIDs will be send to frontend.`, name: 'theming-advanced', type: 'html', private: true, - descriptionHTML: '

Theming

' + descriptionHTML: loc('theming_advanced_description') }) registerSetting({ name: 'converse-theme', - label: 'ConverseJS theme', + label: loc('converse_theme_label'), type: 'select', default: 'peertube' as ConverseJSTheme, private: false, options: [ - { value: 'peertube', label: 'Peertube theme' }, - { value: 'default', label: 'Default ConverseJS theme' }, - { value: 'concord', label: 'ConverseJS concord theme' } + { value: 'peertube', label: loc('peertube') }, + { value: 'default', label: loc('default') }, + { value: 'concord', label: loc('concord') } ] as Array<{value: ConverseJSTheme, label: string}>, - descriptionHTML: 'Please choose the converseJS theme you want to use.' + descriptionHTML: loc('converse_theme_description') }) registerSetting({ name: 'converse-autocolors', - label: 'Automatic color detection', + label: loc('autocolors_label'), type: 'input-checkbox', default: true, private: false, - descriptionHTML: -`Try to auto detect colors from user's current theme.
-When this settings is enabled, the plugin tries to auto-detect colors to apply to the chat theme.
-If this is not correctly working for some of your Peertube theme, you can disable this option. -You can report the bug on the official - - issue tracker -. Don't forget to specify which theme is not working.` + descriptionHTML: loc('autocolors_description') }) registerSetting({ name: 'chat-style', - label: 'Webchat iframe style attribute', + label: loc('chat_style_label'), type: 'input-textarea', default: '', - descriptionHTML: -`Additional styles to be added on the iframe style attribute.
-Example: height:400px;`, + descriptionHTML: loc('chat_style_description'), private: false }) @@ -217,26 +237,22 @@ Example: height:400px;`, name: 'prosody-advanced', type: 'html', private: true, - descriptionHTML: '

Chat server advanced settings

' + descriptionHTML: loc('prosody_advanced_description') }) registerSetting({ name: 'chat-help-builtin-prosody', type: 'html', - label: 'Prosody server', - descriptionHTML: `This plugin uses the Prosody XMPP server to handle chat rooms.
-This plugin comes with a Prosody AppImage, that will be used to run the service.`, + label: loc('help_builtin_prosody_label'), + descriptionHTML: loc('help_builtin_prosody_description'), private: true }) registerSetting({ name: 'use-system-prosody', type: 'input-checkbox', - label: 'Use system Prosody', - descriptionHTML: `Warning: don't check this settings if you are not sure of what you are doing.
-By checking this settings, your Peertube will use the Prosody server that comes with your system, -and not the embeded AppImage.
-Only use this if you encounter problems with the embedded Prosody.`, + label: loc('system_prosody_label'), + descriptionHTML: loc('system_prosody_description'), private: true, default: false }) @@ -244,142 +260,91 @@ Only use this if you encounter problems with the embedded Prosody.`, registerSetting({ name: 'disable-websocket', type: 'input-checkbox', - label: 'Disable Websocket', - descriptionHTML: `With Peertube >= 5.0.0, this plugin try to use Websocket connection for chatting. -If the user's browser or connection is not compatible, the browser will automatically fallback on the BOSH protocol. -
-But in rare case, this can fail. For example if you have a reverse proxy in front of Peertube that does not -allow Websocket connection for plugins. -In this case, you can check this settings to disable Websocket connections.`, + label: loc('disable_websocket_label'), + descriptionHTML: loc('disable_websocket_description'), private: true, default: false }) registerSetting({ name: 'prosody-port', - label: 'Prosody port', + label: loc('prosody_port_label'), type: 'input', default: '52800', private: true, - descriptionHTML: -`The port that will be used by the builtin Prosody server.
-Change it if this port is already in use on your server.
-You can close this port on your firewall, it will not be accessed from the outer world.` + descriptionHTML: loc('prosody_port_description') }) registerSetting({ name: 'prosody-peertube-uri', - label: 'Peertube url for API calls', + label: loc('prosody_peertube_uri_label'), type: 'input', default: '', private: true, - descriptionHTML: -`Please let this settings empty if you don't know what you are doing.
-In some rare case, Prosody can't call Peertube's API from its public URI. -You can use this field to customise Peertube's URI for Prosody modules -(for example with «http://localhost:9000» or «http://127.0.0.1:9000»).` + descriptionHTML: loc('prosody_peertube_uri_description') }) registerSetting({ name: 'prosody-muc-log-by-default', - label: 'Log rooms content by default', + label: loc('prosody_muc_log_by_default_label'), type: 'input-checkbox', default: true, private: true, - descriptionHTML: -`If checked, room contents will be saved by default. -Any user that join a room will see what was written before he joins.
-Please note that it is always possible to enable/disable the content -archiving for a specific room, by editing its properties. -` + descriptionHTML: loc('prosody_muc_log_by_default_description') }) registerSetting({ name: 'prosody-muc-expiration', - label: 'Room logs expiration', + label: loc('prosody_muc_expiration_label'), type: 'input', default: '1w', private: true, - descriptionHTML: -`You can choose here how long the chatting room's content is kept by the server. The value can be: -
    -
  • 60: the content will be saved for 60 seconds. You can replace 60 by any integer value.
  • -
  • 1d: the content will be saved for 1 day. You can replace 1 by any integer value.
  • -
  • 1w: the content will be saved for 1 week. You can replace 1 by any integer value.
  • -
  • 1m: the content will be saved for 1 month. You can replace 1 by any integer value.
  • -
  • 1y: the content will be saved for 1 year. You can replace 1 by any integer value.
  • -
  • never: the content will never expire, and will be kept forever.
  • -
` + descriptionHTML: loc('prosody_muc_expiration_description') }) registerSetting({ name: 'prosody-c2s', - label: 'Enable client to server connections', + label: loc('prosody_c2s_label'), type: 'input-checkbox', default: false, private: true, - descriptionHTML: -`Enable XMPP clients to connect to the builtin Prosody server.
-This option alone only allows connections from localhost clients.` + descriptionHTML: loc('prosody_c2s_description') }) registerSetting({ name: 'prosody-c2s-port', - label: 'Prosody client to server port', + label: loc('prosody_c2s_port_label'), type: 'input', default: '52822', private: true, - descriptionHTML: -`The port that will be used by the c2s module of the builtin Prosody server.
-XMPP clients shall use this port to connect.
-Change it if this port is already in use on your server.
-You can keep this port closed on your firewall for now, it will not be accessed from the outer world.` + descriptionHTML: loc('prosody_c2s_port_description') }) registerSetting({ name: 'prosody-components', - label: 'Enable custom Prosody external components', + label: loc('prosody_components_label'), type: 'input-checkbox', default: false, private: true, - descriptionHTML: -`Enable the use of external XMPP components.
-This option alone only allows connections from localhost.
-This feature can for example be used to connect some bots to the chatting rooms.` + descriptionHTML: loc('prosody_components_description') }) registerSetting({ name: 'prosody-components-port', - label: 'Prosody external components port', + label: loc('prosody_components_port_label'), type: 'input', default: '53470', private: true, - descriptionHTML: -`The port that will be used by XMPP components to connect to the Prosody server.
-Change it if this port is already in use on your server.
-You can keep this port closed on your firewall for now, it will not be accessed from the outer world.` + descriptionHTML: loc('prosody_components_port_description') }) registerSetting({ name: 'prosody-components-list', - label: 'External components', + label: loc('prosody_components_list_label'), type: 'input-textarea', default: '', private: true, - descriptionHTML: -`The external components to create: -
    -
  • One per line.
  • -
  • Use the format «component_name:component_secret» (spaces will be trimmed)
  • -
  • You can add comments: everything after the # character will be stripped off, and empty lines ignored
  • -
  • The name can only contain alphanumeric characters and dots
  • -
  • - If the name contains only alphanumeric characters, it will be suffixed with the XMPP domain. - For exemple «bridge» will become «bridge.your_domain.tld». - You can also specify a full domain name, but you have to make sure to configure your DNS correctly. -
  • -
  • Only use alphanumeric characters in the secret passphrase (use at least 15 characters).
  • -
` + descriptionHTML: loc('prosody_components_list_description') }) // ********** settings changes management diff --git a/support/documentation/content/contributing/translate/_index.en.md b/support/documentation/content/contributing/translate/_index.en.md index b45acb80..8b75acce 100644 --- a/support/documentation/content/contributing/translate/_index.en.md +++ b/support/documentation/content/contributing/translate/_index.en.md @@ -7,7 +7,15 @@ chapter=false You can help us to translate this PeerTube plugin by creating or modifying translation files in the `languages` folder. +{{% notice info %}} +For now, translation is done in the git repository. Later in 2023, online translation tools will be set (probably [Weblate](https://weblate.org)). This will make the translation process easier. +{{% /notice %}} + +{{% notice tip %}} Please work on the `develop` branch, and do your commits and pull request on this branch. +{{% /notice %}} + +## Standard application strings If the language you are interesting in does not exist yet, create a file `code.json` in the `languages` folder, where `code` is the language code. The language code must be the same as the Peertube's langage code (see [Peertube documentation](https://github.com/Chocobozzz/PeerTube/blob/develop/support/doc/translation.md)). @@ -19,3 +27,29 @@ Translation strings are set in the language file as follow: - the JSON key is the english string (see existing keys in the [french translation file](languages/fr.json)). - the JSON value is the translating string - NB: there is no english translation file (this is how translation works for peertube's plugins) + +## Settings translations + +In the plugin settings page, there are more complex strings. +They can be HTML code, with newlines, HTML tags, ... +This is not suitable for the JSON format. + +That's why the process is a little bit different for settings strings. + +Settings strings are defined in [YAML files](https://en.wikipedia.org/wiki/YAML). +They don't use the english text as key, but a codified key, like `list_rooms_label`. + +On the contrary of the standards application strings, there is also a configuration file for the english language. + +These files are in the folder `languages/settings`. If the file for the language that you are interested in does not exist, just create a new file +named `code.yml`, where `code` is the language code (see above). + +Then, you can copy YAML keys from the reference file `languages/settings/en.yml`, and translate strings. + +If you don't want to translate a string, you can ignore it, or use `null` or `~` as value. + +{{% notice warning %}} +There might be some «very technical» strings. If you are not 100% sure of +the meaning, or of your translation, you better not translate it, +so it will display in english. +{{% /notice %}} diff --git a/support/documentation/content/contributing/translate/_index.fr.md b/support/documentation/content/contributing/translate/_index.fr.md index dabc6776..afef1a4c 100644 --- a/support/documentation/content/contributing/translate/_index.fr.md +++ b/support/documentation/content/contributing/translate/_index.fr.md @@ -7,7 +7,18 @@ chapter=false Vous pouvez nous aider à traduire ce plugin Peertube en créant ou modifiant des fichiers de traduction dans le dossier `languages`. +{{% notice info %}} +Pour le moment, les traductions se font directement dans le dépôt git. +Plus tard en 2023, des outils de traduction en ligne seront mis en place +(probablement [Weblate](https://weblate.org)). +Le processus de traduction en sera plus simple. +{{% /notice %}} + +{{% notice tip %}} Merci de travailler sur la branche `develop`, et de faire vos _pull request_ sur cette branche. +{{% /notice %}} + +## Chaîne applicatives standard Si la langue dans laquelle vous souhaitez traduire n'existe pas encore, créez un fichier `code.json` dans le dossier `languages`, où `code` est le code langue. Le code langue doit être dans le même format que les codes langues de Peertube (voir la [documentation Peertube](https://github.com/Chocobozzz/PeerTube/blob/develop/support/doc/translation.md)). @@ -19,3 +30,36 @@ Les traductions sont sous la forme suivante dans le fichier de langue : - les clés JSON sont le texte en anglais (voir les clés existantes dans [le fichier de traduction français](languages/fr.json), qui fait référence) - la valeur JSON est la traduction - NB: il n'y a pas de fichier de traduction pour l'anglais (c'est la façon de fonctionner de Peertube) + +## Traduction des paramètres du plugin + +Dans la page des paramètres du plugin, il y a des chaînes de texte plus compliquées. +Elles peuvent contenir du code HTML, des retours à la ligne, ... +Il est donc compliqué de les maintenir dans des fichiers JSON. + +C'est pourquoi le processus de traduction est différent pour les traductions de paramètres. + +Les traductions des paramètres sont définies dans des fichiers [YAML](https://fr.wikipedia.org/wiki/YAML). +Elles n'utilisent pas l'anglais comme clé, mais des clés standardisées, +comme par exemple `list_rooms_label`. + +Au contraire des chaînes applicatives standard, il y a aussi un fichier de +configuration pour l'anglais. + +Ces fichiers sont dans le dossier `languages/settings`. +Si le fichier de la langue qui vous intéresse n'existe pas, vous +n'avez qu'à créer un fichier nommé `code.yml` où `code` est le code +de la langue (voir plus haut). + +Ensuite, vous pouvez copier les clés du fichier HTML de référence +`languages/settings/en.yml`, et traduire les chaînes de texte. + +Si vous ne voulez pas traduire une chaîne, vous pouvez l'ignorer, +ou utiliser `null` ou `~` comme valeur. + +{{% notice warning %}} +Il peut y avoir des chaînes «assez techniques». +Si vous n'êtes pas sûr⋅e à 100% du sens, ou de la traduction, +il vaut mieux ne pas la traduire du tout ; +ainsi la version anglaise s'affichera. +{{% /notice %}}