((res, rej) => {
const port = parallelTests() ? randomInt(1025, 2000) : 1025
this.emails = emailsCollection
@@ -24,11 +31,26 @@ class MockSmtpServer {
ip: '127.0.0.1',
smtp: port,
disableWeb: true,
- silent: true
+ silent: true,
+ outgoingHost,
+ outgoingPort
})
this.maildev.on('new', email => {
this.emails.push(email)
+
+ if (outgoingHost || outgoingPort) {
+ this.relayingEmail = new Promise(resolve => {
+ this.maildev.relayMail(email, function (err) {
+ if (err) return console.log(err)
+
+ console.log('Email has been relayed!')
+
+ this.relayingEmail = undefined
+ resolve()
+ })
+ })
+ }
})
this.maildev.listen(err => {
@@ -41,9 +63,13 @@ class MockSmtpServer {
})
}
- kill () {
+ async kill () {
if (!this.maildev) return
+ if (this.relayingEmail) {
+ await this.relayingEmail
+ }
+
this.maildev.close()
this.maildev = null
diff --git a/packages/tests/src/shared/notifications.ts b/packages/tests/src/shared/notifications.ts
index 72abc9b9b..39fa4169c 100644
--- a/packages/tests/src/shared/notifications.ts
+++ b/packages/tests/src/shared/notifications.ts
@@ -77,11 +77,13 @@ async function waitUntilNotification (options: {
await waitJobs([ server ])
}
-async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
+async function checkNewVideoFromSubscription (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+ }
+) {
const { videoName, shortUUID } = options
const notificationType = UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION
@@ -107,11 +109,13 @@ async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewLiveFromSubscription (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
+async function checkNewLiveFromSubscription (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+ }
+) {
const { videoName, shortUUID } = options
const notificationType = UserNotificationType.NEW_LIVE_FROM_SUBSCRIPTION
@@ -137,11 +141,13 @@ async function checkNewLiveFromSubscription (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkMyVideoIsPublished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
+async function checkMyVideoIsPublished (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+ }
+) {
const { videoName, shortUUID } = options
const notificationType = UserNotificationType.MY_VIDEO_PUBLISHED
@@ -165,11 +171,13 @@ async function checkMyVideoIsPublished (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkVideoStudioEditionIsFinished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
+async function checkVideoStudioEditionIsFinished (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+ }
+) {
const { videoName, shortUUID } = options
const notificationType = UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED
@@ -193,13 +201,15 @@ async function checkVideoStudioEditionIsFinished (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- url: string
- success: boolean
- checkType: CheckerType
-}) {
+async function checkMyVideoImportIsFinished (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ url: string
+ success: boolean
+ checkType: CheckerType
+ }
+) {
const { videoName, shortUUID, url, success } = options
const notificationType = success ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS : UserNotificationType.MY_VIDEO_IMPORT_ERROR
@@ -219,9 +229,11 @@ async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
function emailNotificationFinder (email: object) {
const text: string = email['text']
- const toFind = success ? ' finished' : ' error'
+ const toFind = success
+ ? /\bfinished\b/
+ : /\berror\b/
- return text.includes(url) && text.includes(toFind)
+ return text.includes(url) && !!text.match(toFind)
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
@@ -229,10 +241,12 @@ async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
// ---------------------------------------------------------------------------
-async function checkUserRegistered (options: CheckerBaseParams & {
- username: string
- checkType: CheckerType
-}) {
+async function checkUserRegistered (
+ options: CheckerBaseParams & {
+ username: string
+ checkType: CheckerType
+ }
+) {
const { username } = options
const notificationType = UserNotificationType.NEW_USER_REGISTRATION
@@ -257,11 +271,13 @@ async function checkUserRegistered (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkRegistrationRequest (options: CheckerBaseParams & {
- username: string
- registrationReason: string
- checkType: CheckerType
-}) {
+async function checkRegistrationRequest (
+ options: CheckerBaseParams & {
+ username: string
+ registrationReason: string
+ checkType: CheckerType
+ }
+) {
const { username, registrationReason } = options
const notificationType = UserNotificationType.NEW_USER_REGISTRATION_REQUEST
@@ -287,13 +303,15 @@ async function checkRegistrationRequest (options: CheckerBaseParams & {
// ---------------------------------------------------------------------------
-async function checkNewActorFollow (options: CheckerBaseParams & {
- followType: 'channel' | 'account'
- followerName: string
- followerDisplayName: string
- followingDisplayName: string
- checkType: CheckerType
-}) {
+async function checkNewActorFollow (
+ options: CheckerBaseParams & {
+ followType: 'channel' | 'account'
+ followerName: string
+ followerDisplayName: string
+ followingDisplayName: string
+ checkType: CheckerType
+ }
+) {
const { followType, followerName, followerDisplayName, followingDisplayName } = options
const notificationType = UserNotificationType.NEW_FOLLOW
@@ -327,10 +345,12 @@ async function checkNewActorFollow (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewInstanceFollower (options: CheckerBaseParams & {
- followerHost: string
- checkType: CheckerType
-}) {
+async function checkNewInstanceFollower (
+ options: CheckerBaseParams & {
+ followerHost: string
+ checkType: CheckerType
+ }
+) {
const { followerHost } = options
const notificationType = UserNotificationType.NEW_INSTANCE_FOLLOWER
@@ -354,17 +374,19 @@ async function checkNewInstanceFollower (options: CheckerBaseParams & {
function emailNotificationFinder (email: object) {
const text: string = email['text']
- return text.includes('instance has a new follower') && text.includes(followerHost)
+ return text.includes('PeerTube has a new follower') && text.includes(followerHost)
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
- followerHost: string
- followingHost: string
- checkType: CheckerType
-}) {
+async function checkAutoInstanceFollowing (
+ options: CheckerBaseParams & {
+ followerHost: string
+ followingHost: string
+ checkType: CheckerType
+ }
+) {
const { followerHost, followingHost } = options
const notificationType = UserNotificationType.AUTO_INSTANCE_FOLLOWING
@@ -391,19 +413,21 @@ async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
function emailNotificationFinder (email: object) {
const text: string = email['text']
- return text.includes(' automatically followed a new instance') && text.includes(followingHost)
+ return text.match(/\bautomatically followed\b/) && text.includes(followingHost)
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkCommentMention (options: CheckerBaseParams & {
- shortUUID: string
- commentId: number
- threadId: number
- byAccountDisplayName: string
- checkType: CheckerType
-}) {
+async function checkCommentMention (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ commentId: number
+ threadId: number
+ byAccountDisplayName: string
+ checkType: CheckerType
+ }
+) {
const { shortUUID, commentId, threadId, byAccountDisplayName } = options
const notificationType = UserNotificationType.COMMENT_MENTION
@@ -425,7 +449,7 @@ async function checkCommentMention (options: CheckerBaseParams & {
function emailNotificationFinder (email: object) {
const text: string = email['text']
- return text.includes(' mentioned ') && text.includes(shortUUID) && text.includes(byAccountDisplayName)
+ return text.match(/\bmentioned\b/) && text.includes(shortUUID) && text.includes(byAccountDisplayName)
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
@@ -433,13 +457,15 @@ async function checkCommentMention (options: CheckerBaseParams & {
let lastEmailCount = 0
-async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
- shortUUID: string
- commentId: number
- threadId: number
- checkType: CheckerType
- approval?: boolean // default false
-}) {
+async function checkNewCommentOnMyVideo (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ commentId: number
+ threadId: number
+ checkType: CheckerType
+ approval?: boolean // default false
+ }
+) {
const { server, shortUUID, commentId, threadId, checkType, emails, approval = false } = options
const notificationType = UserNotificationType.NEW_COMMENT_ON_MY_VIDEO
@@ -468,7 +494,7 @@ async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
const text = email['text']
return text.includes(commentUrl) &&
- (approval && text.includes('requires approval')) ||
+ (approval && text.includes('requires approval')) ||
(!approval && !text.includes('requires approval'))
}
@@ -481,11 +507,13 @@ async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
}
}
-async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
+async function checkNewVideoAbuseForModerators (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+ }
+) {
const { shortUUID, videoName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
@@ -511,12 +539,14 @@ async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewAbuseMessage (options: CheckerBaseParams & {
- abuseId: number
- message: string
- toEmail: string
- checkType: CheckerType
-}) {
+async function checkNewAbuseMessage (
+ options: CheckerBaseParams & {
+ abuseId: number
+ message: string
+ toEmail: string
+ checkType: CheckerType
+ }
+) {
const { abuseId, message, toEmail } = options
const notificationType = UserNotificationType.ABUSE_NEW_MESSAGE
@@ -543,11 +573,13 @@ async function checkNewAbuseMessage (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkAbuseStateChange (options: CheckerBaseParams & {
- abuseId: number
- state: AbuseStateType
- checkType: CheckerType
-}) {
+async function checkAbuseStateChange (
+ options: CheckerBaseParams & {
+ abuseId: number
+ state: AbuseStateType
+ checkType: CheckerType
+ }
+) {
const { abuseId, state } = options
const notificationType = UserNotificationType.ABUSE_STATE_CHANGE
@@ -578,11 +610,13 @@ async function checkAbuseStateChange (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
+async function checkNewCommentAbuseForModerators (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+ }
+) {
const { shortUUID, videoName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
@@ -608,10 +642,12 @@ async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
- displayName: string
- checkType: CheckerType
-}) {
+async function checkNewAccountAbuseForModerators (
+ options: CheckerBaseParams & {
+ displayName: string
+ checkType: CheckerType
+ }
+) {
const { displayName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
@@ -637,11 +673,13 @@ async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
+async function checkVideoAutoBlacklistForModerators (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+ }
+) {
const { shortUUID, videoName } = options
const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
@@ -667,11 +705,13 @@ async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- blacklistType: 'blacklist' | 'unblacklist'
-}) {
+async function checkNewBlacklistOnMyVideo (
+ options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ blacklistType: 'blacklist' | 'unblacklist'
+ }
+) {
const { videoName, shortUUID, blacklistType } = options
const notificationType = blacklistType === 'blacklist'
? UserNotificationType.BLACKLIST_ON_MY_VIDEO
@@ -687,21 +727,24 @@ async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
}
function emailNotificationFinder (email: object) {
- const text = email['text']
- const blacklistText = blacklistType === 'blacklist'
- ? 'blacklisted'
- : 'unblacklisted'
+ const text: string = email['text']
- return text.includes(shortUUID) && text.includes(blacklistText)
+ const blacklistReg = blacklistType === 'blacklist'
+ ? /\bblocked\b/
+ : /\bunblocked\b/
+
+ return text.includes(shortUUID) && !!text.match(blacklistReg)
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder, checkType: 'presence' })
}
-async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
- latestVersion: string
- checkType: CheckerType
-}) {
+async function checkNewPeerTubeVersion (
+ options: CheckerBaseParams & {
+ latestVersion: string
+ checkType: CheckerType
+ }
+) {
const { latestVersion } = options
const notificationType = UserNotificationType.NEW_PEERTUBE_VERSION
@@ -728,11 +771,13 @@ async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewPluginVersion (options: CheckerBaseParams & {
- pluginType: PluginType_Type
- pluginName: string
- checkType: CheckerType
-}) {
+async function checkNewPluginVersion (
+ options: CheckerBaseParams & {
+ pluginType: PluginType_Type
+ pluginName: string
+ checkType: CheckerType
+ }
+) {
const { pluginName, pluginType } = options
const notificationType = UserNotificationType.NEW_PLUGIN_VERSION
@@ -759,15 +804,17 @@ async function checkNewPluginVersion (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkMyVideoTranscriptionGenerated (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- language: {
- id: string
- label: string
+async function checkMyVideoTranscriptionGenerated (
+ options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ language: {
+ id: string
+ label: string
+ }
+ checkType: CheckerType
}
- checkType: CheckerType
-}) {
+) {
const { videoName, shortUUID, language } = options
const notificationType = UserNotificationType.MY_VIDEO_TRANSCRIPTION_GENERATED
@@ -872,11 +919,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
export {
type CheckerType,
type CheckerBaseParams,
-
getAllNotificationsSettings,
-
waitUntilNotification,
-
checkMyVideoImportIsFinished,
checkUserRegistered,
checkAutoInstanceFollowing,
@@ -904,11 +948,13 @@ export {
// ---------------------------------------------------------------------------
-async function checkNotification (options: CheckerBaseParams & {
- notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
- emailNotificationFinder: (email: object) => boolean
- checkType: CheckerType
-}) {
+async function checkNotification (
+ options: CheckerBaseParams & {
+ notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
+ emailNotificationFinder: (email: object) => boolean
+ checkType: CheckerType
+ }
+) {
const { server, token, checkType, notificationChecker, emailNotificationFinder, socketNotifications, emails } = options
const check = options.check || { web: true, mail: true }
diff --git a/scripts/build/server.sh b/scripts/build/server.sh
index 7d0acd1ac..e605164de 100755
--- a/scripts/build/server.sh
+++ b/scripts/build/server.sh
@@ -10,6 +10,7 @@ npm run tsc -- -b --verbose server/tsconfig.json
npm run resolve-tspaths:server
cp -r "./server/core/static" "./server/core/assets" ./dist/core
+cp -r "./server/locales" ./dist
cp "./server/scripts/upgrade.sh" "./dist/scripts"
mkdir -p ./client/dist && cp -r ./client/src/assets ./client/dist
diff --git a/scripts/dev/server.sh b/scripts/dev/server.sh
index 569f3c4c9..d6f89e0dc 100755
--- a/scripts/dev/server.sh
+++ b/scripts/dev/server.sh
@@ -19,6 +19,7 @@ mkdir -p "./dist/core/lib"
npm run tsc -- -b -v --incremental server/tsconfig.json
npm run resolve-tspaths:server
-cp -r ./server/core/static ./server/core/assets ./dist/core
+cp -r "./server/core/static" "./server/core/assets" ./dist/core
+cp -r "./server/locales" ./dist
./node_modules/.bin/tsc-watch --build --preserveWatchOutput --verbose --onSuccess 'sh -c "npm run resolve-tspaths:server && NODE_ENV=dev node dist/server"' server/tsconfig.json
diff --git a/scripts/i18n/update.sh b/scripts/i18n/update.sh
index aaabf76dd..64b9776e5 100755
--- a/scripts/i18n/update.sh
+++ b/scripts/i18n/update.sh
@@ -25,3 +25,7 @@ node ./node_modules/.bin/xliffmerge -p ./.xliffmerge.json $locales
# Add our strings too
cd ../
npm run i18n:create-custom-files
+
+# Generate server translations
+node ./node_modules/.bin/i18next -c server/.i18next-parser.config.ts server/core/**/*.{ts,hbs}
+
diff --git a/server/.i18next-parser.config.ts b/server/.i18next-parser.config.ts
new file mode 100644
index 000000000..844dd282f
--- /dev/null
+++ b/server/.i18next-parser.config.ts
@@ -0,0 +1,145 @@
+import { I18N_LOCALES } from '../packages/core-utils/dist/i18n/i18n.js'
+import { UserConfig } from 'i18next-parser'
+
+export default {
+ contextSeparator: '_',
+ // Key separator used in your translation keys
+
+ createOldCatalogs: false,
+ // Save the \_old files
+
+ defaultNamespace: 'translation',
+ // Default namespace used in your i18next config
+
+ defaultValue: (_locale, _namespace, key, _value) => {
+ return key as string
+ },
+ // Default value to give to keys with no value
+ // You may also specify a function accepting the locale, namespace, key, and value as arguments
+
+ indentation: 2,
+ // Indentation of the catalog files
+
+ keepRemoved: false,
+ // Keep keys from the catalog that are no longer in code
+ // You may either specify a boolean to keep or discard all removed keys.
+ // You may also specify an array of patterns: the keys from the catalog that are no long in the code but match one of the patterns will be kept.
+ // The patterns are applied to the full key including the namespace, the parent keys and the separators.
+
+ keySeparator: false,
+ // Key separator used in your translation keys
+ // If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
+
+ // see below for more details
+ lexers: {
+ hbs: [
+ {
+ lexer: 'HandlebarsLexer',
+ functions: [ 't' ]
+ }
+ ],
+ handlebars: [ 'HandlebarsLexer' ],
+
+ htm: [ 'HTMLLexer' ],
+ html: [ 'HTMLLexer' ],
+
+ mjs: [ 'JavascriptLexer' ],
+ js: [ 'JavascriptLexer' ], // if you're writing jsx inside .js files, change this to JsxLexer
+ ts: [
+ {
+ lexer: 'JavascriptLexer',
+ functions: [ 't', 'tu' ]
+ }
+ ],
+ jsx: [ 'JsxLexer' ],
+ tsx: [ 'JsxLexer' ],
+
+ default: [ 'JavascriptLexer' ]
+ },
+
+ lineEnding: 'auto',
+ // Control the line ending. See options at https://github.com/ryanve/eol
+
+ locales: Object.keys(I18N_LOCALES),
+ // An array of the locales in your applications
+
+ namespaceSeparator: false,
+ // Namespace separator used in your translation keys
+ // If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
+
+ output: 'server/locales/$LOCALE/$NAMESPACE.json',
+ // Supports $LOCALE and $NAMESPACE injection
+ // Supports JSON (.json) and YAML (.yml) file formats
+ // Where to write the locale files relative to process.cwd()
+
+ pluralSeparator: '_',
+ // Plural separator used in your translation keys
+ // If you want to use plain english keys, separators such as `_` might conflict. You might want to set `pluralSeparator` to a different string that does not occur in your keys.
+ // If you don't want to generate keys for plurals (for example, in case you are using ICU format), set `pluralSeparator: false`.
+
+ input: undefined,
+ // An array of globs that describe where to look for source files
+ // relative to the location of the configuration file
+
+ sort: false,
+ // Whether or not to sort the catalog. Can also be a [compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#parameters)
+
+ verbose: false,
+ // Display info about the parsing including some stats
+
+ failOnWarnings: false,
+ // Exit with an exit code of 1 on warnings
+
+ failOnUpdate: false,
+ // Exit with an exit code of 1 when translations are updated (for CI purpose)
+
+ customValueTemplate: null,
+ // If you wish to customize the value output the value as an object, you can set your own format.
+ //
+ // - ${defaultValue} is the default value you set in your translation function.
+ // - ${filePaths} will be expanded to an array that contains the absolute
+ // file paths where the translations originated in, in case e.g., you need
+ // to provide translators with context
+ //
+ // Any other custom property will be automatically extracted from the 2nd
+ // argument of your `t()` function or tOptions in
+ //
+ // Example:
+ // For `t('my-key', {maxLength: 150, defaultValue: 'Hello'})` in
+ // /path/to/your/file.js,
+ //
+ // Using the following customValueTemplate:
+ //
+ // customValueTemplate: {
+ // message: "${defaultValue}",
+ // description: "${maxLength}",
+ // paths: "${filePaths}",
+ // }
+ //
+ // Will result in the following item being extracted:
+ //
+ // "my-key": {
+ // "message": "Hello",
+ // "description": 150,
+ // "paths": ["/path/to/your/file.js"]
+ // }
+
+ resetDefaultValueLocale: null,
+ // The locale to compare with default values to determine whether a default value has been changed.
+ // If this is set and a default value differs from a translation in the specified locale, all entries
+ // for that key across locales are reset to the default value, and existing translations are moved to
+ // the `_old` file.
+
+ i18nextOptions: null,
+ // If you wish to customize options in internally used i18next instance, you can define an object with any
+ // configuration property supported by i18next (https://www.i18next.com/overview/configuration-options).
+ // { compatibilityJSON: 'v3' } can be used to generate v3 compatible plurals.
+
+ yamlOptions: null
+ // If you wish to customize options for yaml output, you can define an object here.
+ // Configuration options are here (https://github.com/nodeca/js-yaml#dump-object---options-).
+ // Example:
+ // {
+ // lineWidth: -1,
+ // }
+} satisfies UserConfig
diff --git a/server/core/assets/email-templates/abuse-new-message/html.hbs b/server/core/assets/email-templates/abuse-new-message/html.hbs
new file mode 100644
index 000000000..7d03c24e3
--- /dev/null
+++ b/server/core/assets/email-templates/abuse-new-message/html.hbs
@@ -0,0 +1,10 @@
+{{! New message on abuse report }}
+{{#> base title=(t "New message on abuse report")}}
+
+ {{{t "A new message by {messageAccountName} was posted on abuse report #{abuseId} " messageAccountName=messageAccountName abuseUrl=abuseUrl abuseId=abuseId}}}
+
+
+ {{messageText}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/abuse-new-message/html.pug b/server/core/assets/email-templates/abuse-new-message/html.pug
deleted file mode 100644
index c1d452e7d..000000000
--- a/server/core/assets/email-templates/abuse-new-message/html.pug
+++ /dev/null
@@ -1,11 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | New message on abuse report
-
-block content
- p
- | A new message by #{messageAccountName} was posted on #[a(href=abuseUrl) abuse report ##{abuseId}] on #{instanceName}
- blockquote #{messageText}
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/abuse-state-change/html.hbs b/server/core/assets/email-templates/abuse-state-change/html.hbs
new file mode 100644
index 000000000..91145092a
--- /dev/null
+++ b/server/core/assets/email-templates/abuse-state-change/html.hbs
@@ -0,0 +1,10 @@
+{{! Abuse report state changed }}
+{{#> base title=(t "Abuse report state changed")}}
+
+ {{#if isAccepted}}
+ {{{t "Your abuse report #{abuseId} on {instanceName} has been accepted." abuseUrl=abuseUrl abuseId=abuseId instanceName=instanceName}}}
+ {{else}}
+ {{{t "Your abuse report #{abuseId} on {instanceName} has been rejected." abuseUrl=abuseUrl abuseId=abuseId instanceName=instanceName}}}
+ {{/if}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/abuse-state-change/html.pug b/server/core/assets/email-templates/abuse-state-change/html.pug
deleted file mode 100644
index bb243e729..000000000
--- a/server/core/assets/email-templates/abuse-state-change/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | Abuse report state changed
-
-block content
- p
- | #[a(href=abuseUrl) Your abuse report ##{abuseId}] on #{instanceName} has been #{isAccepted ? 'accepted' : 'rejected'}
diff --git a/server/core/assets/email-templates/account-abuse-new/html.hbs b/server/core/assets/email-templates/account-abuse-new/html.hbs
new file mode 100644
index 000000000..231dc3cef
--- /dev/null
+++ b/server/core/assets/email-templates/account-abuse-new/html.hbs
@@ -0,0 +1,18 @@
+{{! An account is pending moderation }}
+{{#> base title=(t "An account is pending moderation")}}
+
+ {{#if isLocal}}
+ {{{t "{instanceName} received an abuse report for the account: {accountDisplayName} " accountUrl=accountUrl accountDisplayName=accountDisplayName instanceName=instanceName}}}
+ {{else}}
+ {{{t "{instanceName} received an abuse report for the remote account: {accountDisplayName} " accountUrl=accountUrl accountDisplayName=accountDisplayName instanceName=instanceName}}}
+ {{/if}}
+
+
+
+ {{t "The reporter, {reporter}, cited the following reason(s):" reporter=reporter}}
+
+
+ {{reason}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/account-abuse-new/html.pug b/server/core/assets/email-templates/account-abuse-new/html.pug
deleted file mode 100644
index e4c0366fb..000000000
--- a/server/core/assets/email-templates/account-abuse-new/html.pug
+++ /dev/null
@@ -1,14 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | An account is pending moderation
-
-block content
- p
- | #[a(href=WEBSERVER.URL) #{instanceName}] received an abuse report for the #{isLocal ? '' : 'remote '}account
- a(href=accountUrl) #{accountDisplayName}
-
- p The reporter, #{reporter}, cited the following reason(s):
- blockquote #{reason}
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/common/base.pug b/server/core/assets/email-templates/common/base.pug
deleted file mode 100644
index 8f15f2703..000000000
--- a/server/core/assets/email-templates/common/base.pug
+++ /dev/null
@@ -1,219 +0,0 @@
-//-
- The email background color is defined in three places:
- 1. body tag: for most email clients
- 2. center tag: for Gmail and Inbox mobile apps and web versions of Gmail, GSuite, Inbox, Yahoo, AOL, Libero, Comcast, freenet, Mail.ru, Orange.fr
- 3. mso conditional: For Windows 10 Mail
-doctype html
-head
- // This template is heavily adapted from the Cerberus Fluid template. Kudos to them!
- meta(charset='utf-8')
- //- utf-8 works for most cases
- meta(name='viewport' content='width=device-width')
- //- Forcing initial-scale shouldn't be necessary
- meta(http-equiv='X-UA-Compatible' content='IE=edge')
- //- Use the latest (edge) version of IE rendering engine
- meta(name='x-apple-disable-message-reformatting')
- //- Disable auto-scale in iOS 10 Mail entirely
- meta(name='format-detection' content='telephone=no,address=no,email=no,date=no,url=no')
- //- Tell iOS not to automatically link certain text strings.
- meta(name='color-scheme' content='light')
- meta(name='supported-color-schemes' content='light')
- //- The title tag shows in email notifications, like Android 4.4.
- title #{subject}
- //- What it does: Makes background images in 72ppi Outlook render at correct size.
- //if gte mso 9
- xml
- o:officedocumentsettings
- o:allowpng
- o:pixelsperinch 96
- //- CSS Reset : BEGIN
- style.
- /* What it does: Tells the email client that only light styles are provided but the client can transform them to dark. A duplicate of meta color-scheme meta tag above. */
- :root {
- color-scheme: light;
- supported-color-schemes: light;
- }
- /* What it does: Remove spaces around the email design added by some email clients. */
- /* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
- html,
- body {
- margin: 0 auto !important;
- padding: 0 !important;
- height: 100% !important;
- width: 100% !important;
- }
- /* What it does: Stops email clients resizing small text. */
- * {
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
- }
- /* What it does: Centers email on Android 4.4 */
- div[style*="margin: 16px 0"] {
- margin: 0 !important;
- }
- /* What it does: forces Samsung Android mail clients to use the entire viewport */
- #MessageViewBody, #MessageWebViewDiv{
- width: 100% !important;
- }
- /* What it does: Stops Outlook from adding extra spacing to tables. */
- table,
- td {
- mso-table-lspace: 0pt !important;
- mso-table-rspace: 0pt !important;
- }
- /* What it does: Fixes webkit padding issue. */
- table {
- border-spacing: 0 !important;
- border-collapse: collapse !important;
- table-layout: fixed !important;
- margin: 0 auto !important;
- }
- /* What it does: Uses a better rendering method when resizing images in IE. */
- img {
- -ms-interpolation-mode:bicubic;
- }
- a {
- color: #{fg};
- }
- a:not(.no-color) {
- font-weight: 600;
- text-decoration: underline;
- text-decoration-color: #{primary};
- text-underline-offset: 0.25em;
- text-decoration-thickness: 0.15em;
- }
- /* What it does: A work-around for email clients meddling in triggered links. */
- a[x-apple-data-detectors], /* iOS */
- .unstyle-auto-detected-links a,
- .aBn {
- border-bottom: 0 !important;
- cursor: default !important;
- color: inherit !important;
- text-decoration: none !important;
- font-size: inherit !important;
- font-family: inherit !important;
- font-weight: inherit !important;
- line-height: inherit !important;
- }
- /* What it does: Prevents Gmail from displaying a download button on large, non-linked images. */
- .a6S {
- display: none !important;
- opacity: 0.01 !important;
- }
- /* What it does: Prevents Gmail from changing the text color in conversation threads. */
- .im {
- color: inherit !important;
- }
- /* If the above doesn't work, add a .g-img class to any image in question. */
- img.g-img + div {
- display: none !important;
- }
- /* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
- /* Create one of these media queries for each additional viewport size you'd like to fix */
- /* iPhone 4, 4S, 5, 5S, 5C, and 5SE */
- @media only screen and (min-device-width: 320px) and (max-device-width: 374px) {
- u ~ div .email-container {
- min-width: 320px !important;
- }
- }
- /* iPhone 6, 6S, 7, 8, and X */
- @media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
- u ~ div .email-container {
- min-width: 375px !important;
- }
- }
- /* iPhone 6+, 7+, and 8+ */
- @media only screen and (min-device-width: 414px) {
- u ~ div .email-container {
- min-width: 414px !important;
- }
- }
- //- CSS Reset : END
- //- CSS for PeerTube : START
- style.
- blockquote {
- margin-left: 0;
- padding-left: 10px;
- border-left: 2px solid #{primary};
- }
- //- CSS for PeerTube : END
-
-body(width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; color: #{fg}; background-color: #{bg};")
- center(role='article' aria-roledescription='email' lang='en' style='width: 100%; background-color: #{bg};')
- //if mso | IE
- table(role='presentation' border='0' cellpadding='0' cellspacing='0' width='100%' style='background-color: #fff;')
- tr
- td
- //- Visually Hidden Preheader Text : BEGIN
- div(style='max-height:0; overflow:hidden; mso-hide:all;' aria-hidden='true')
- block preheader
- //- Visually Hidden Preheader Text : END
-
- //- Create white space after the desired preview text so email clients don’t pull other distracting text into the inbox preview. Extend as necessary.
- //- Preview Text Spacing Hack : BEGIN
- div(style='display: none; font-size: 1px; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;')
- |
- //- Preview Text Spacing Hack : END
-
- //-
- Set the email width. Defined in two places:
- 1. max-width for all clients except Desktop Windows Outlook, allowing the email to squish on narrow but never go wider than 600px.
- 2. MSO tags for Desktop Windows Outlook enforce a 600px width.
- .email-container(style='max-width: 600px; margin: 0 auto;')
- //if mso
- table(align='center' role='presentation' cellspacing='0' cellpadding='0' border='0' width='600')
- tr
- td
- //- Email Body : BEGIN
- table(align='center' role='presentation' cellspacing='0' cellpadding='0' border='0' width='100%' style='margin: auto;')
- //- 1 Column Text + Button : BEGIN
- tr
- td
- table(role='presentation' cellspacing='0' cellpadding='0' border='0' width='100%')
- tr
- td(style='padding: 20px; font-family: sans-serif; font-size: 15px; line-height: 1.5')
- table(role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%")
- tr
- td(width="40px")
- img(src=`${WEBSERVER.URL}/client/assets/images/icons/icon-192x192.png` width="auto" height="30px" alt="" border="0" style="height: 30px; font-family: sans-serif; font-size: 15px; line-height: 15px;")
- td
- h1(style='margin: 10px 0 10px 0; font-family: sans-serif; font-size: 25px; line-height: 30px; font-weight: normal;')
- block title
- if title
- | #{title}
- else
- | Something requires your attention
- p(style='margin: 0;')
- block body
- if action
- tr
- td(style='padding: 0 20px;')
- //- Button : BEGIN
- table(align='center' role='presentation' cellspacing='0' cellpadding='0' border='0' style='margin: auto;')
- tr
- td(style=`border-radius: 4px; background: ${primary};`)
- a.no-color(href=action.url style=`background: ${primary}; font-family: sans-serif; font-size: 15px; line-height: 15px; text-decoration: none; padding: 13px 17px; display: block; border-radius: 4px; font-weight: bold;`) #{action.text}
- //- Button : END
- //- 1 Column Text + Button : END
- //- Clear Spacer : BEGIN
- tr
- td(aria-hidden='true' height='20' style='font-size: 0px; line-height: 0px;')
- br
- //- Clear Spacer : END
- //- Email Body : END
- //- Email Footer : BEGIN
- unless hideNotificationPreferencesLink
- table(align='center' role='presentation' cellspacing='0' cellpadding='0' border='0' width='100%' style='margin: auto;')
- tr
- td(style='padding: 20px; padding-bottom: 0px; font-family: sans-serif; font-size: 12px; text-align: center;')
- webversion
- a.no-color(href=`${WEBSERVER.URL}/my-account/notifications` style='font-weight: bold;') View in your notifications
- br
- tr
- td(style='padding: 20px; padding-top: 10px; font-family: sans-serif; font-size: 12px; text-align: center;')
- unsubscribe
- a.no-color(href=`${WEBSERVER.URL}/my-account/settings#notifications`) Manage your notification preferences in your profile
- br
- //- Email Footer : END
- //if mso
- //if mso | IE
diff --git a/server/core/assets/email-templates/common/greetings.pug b/server/core/assets/email-templates/common/greetings.pug
deleted file mode 100644
index 2170d3814..000000000
--- a/server/core/assets/email-templates/common/greetings.pug
+++ /dev/null
@@ -1,11 +0,0 @@
-extends base
-
-block body
- if username
- p Hi #{username},
-
- block content
-
- if signature
- p
- | #{signature}
diff --git a/server/core/assets/email-templates/common/html.hbs b/server/core/assets/email-templates/common/html.hbs
new file mode 100644
index 000000000..f6acb6098
--- /dev/null
+++ b/server/core/assets/email-templates/common/html.hbs
@@ -0,0 +1,5 @@
+{{#> base}}
+
+ {{text}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/common/html.pug b/server/core/assets/email-templates/common/html.pug
deleted file mode 100644
index d76168b85..000000000
--- a/server/core/assets/email-templates/common/html.pug
+++ /dev/null
@@ -1,4 +0,0 @@
-extends greetings
-
-block content
- p !{text}
\ No newline at end of file
diff --git a/server/core/assets/email-templates/common/mixins.pug b/server/core/assets/email-templates/common/mixins.pug
deleted file mode 100644
index 831211864..000000000
--- a/server/core/assets/email-templates/common/mixins.pug
+++ /dev/null
@@ -1,7 +0,0 @@
-mixin channel(channel)
- - var handle = `${channel.name}@${channel.host}`
- | #[a(href=`${WEBSERVER.URL}/video-channels/${handle}` title=handle) #{channel.displayName}]
-
-mixin account(account)
- - var handle = `${account.name}@${account.host}`
- | #[a(href=`${WEBSERVER.URL}/accounts/${handle}` title=handle) #{account.displayName}]
diff --git a/server/core/assets/email-templates/contact-form/html.hbs b/server/core/assets/email-templates/contact-form/html.hbs
new file mode 100644
index 000000000..54df5e190
--- /dev/null
+++ b/server/core/assets/email-templates/contact-form/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "Someone just used the contact form")}}
+
+ {{{t "{fromName} sent you a message via the contact form on {instanceName} : " fromName=fromName webserverUrl=WEBSERVER.URL instanceName=instanceName}}}
+
+
+ {{body}}
+
+
+ {{{t "You can contact them at {fromEmail} , or simply reply to this email to get in touch." fromEmail=fromEmail}}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/contact-form/html.pug b/server/core/assets/email-templates/contact-form/html.pug
deleted file mode 100644
index 5a24fa6f1..000000000
--- a/server/core/assets/email-templates/contact-form/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | Someone just used the contact form
-
-block content
- p #{fromName} sent you a message via the contact form on #[a(href=WEBSERVER.URL) #{instanceName}]:
- blockquote(style='white-space: pre-wrap') #{body}
- p You can contact them at #[a(href=`mailto:${fromEmail}`) #{fromEmail}], or simply reply to this email to get in touch.
\ No newline at end of file
diff --git a/server/core/assets/email-templates/follower-on-channel/html.hbs b/server/core/assets/email-templates/follower-on-channel/html.hbs
new file mode 100644
index 000000000..77d58d83e
--- /dev/null
+++ b/server/core/assets/email-templates/follower-on-channel/html.hbs
@@ -0,0 +1,9 @@
+{{#> base title=(t "New follower on your channel")}}
+
+ {{#if accountFollowType}}
+ {{{t "Your account {followingName} has a new subscriber: {followerName} ." followingUrl=followingUrl followingName=followingName followerUrl=followerUrl followerName=followerName}}}
+ {{else}}
+ {{{t "Your channel {followingName} has a new subscriber: {followerName} ." followingUrl=followingUrl followingName=followingName followerUrl=followerUrl followerName=followerName}}}
+ {{/if}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/follower-on-channel/html.pug b/server/core/assets/email-templates/follower-on-channel/html.pug
deleted file mode 100644
index 8a352e90f..000000000
--- a/server/core/assets/email-templates/follower-on-channel/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | New follower on your channel
-
-block content
- p.
- Your #{followType} #[a(href=followingUrl) #{followingName}] has a new subscriber:
- #[a(href=followerUrl) #{followerName}].
\ No newline at end of file
diff --git a/server/core/assets/email-templates/my-user-block-new/html.hbs b/server/core/assets/email-templates/my-user-block-new/html.hbs
new file mode 100644
index 000000000..e3067351b
--- /dev/null
+++ b/server/core/assets/email-templates/my-user-block-new/html.hbs
@@ -0,0 +1,15 @@
+{{#> base title=(t "Your account has been blocked")}}
+
+ {{#if reason}}
+ {{{t "Your account {username} has been blocked by {instanceName} moderators for the following reason:" username=username instanceName=instanceName}}}
+ {{else}}
+ {{{t "Your account {username} has been blocked by {instanceName} moderators." username=username instanceName=instanceName}}}
+ {{/if}}
+
+
+ {{#if reason}}
+ {{reason}}
+ {{/if}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/my-user-unblocked/html.hbs b/server/core/assets/email-templates/my-user-unblocked/html.hbs
new file mode 100644
index 000000000..4e12e94d3
--- /dev/null
+++ b/server/core/assets/email-templates/my-user-unblocked/html.hbs
@@ -0,0 +1,5 @@
+{{#> base title=(t "Your account has been unblocked")}}
+
+ {{{t "Your account {username} has been unblocked by {instanceName} moderators." username=username instanceName=instanceName}}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/partials/base.hbs b/server/core/assets/email-templates/partials/base.hbs
new file mode 100644
index 000000000..999d7200b
--- /dev/null
+++ b/server/core/assets/email-templates/partials/base.hbs
@@ -0,0 +1,268 @@
+{{!
+ The email background color is defined in three places:
+ 1. body tag: for most email clients
+ 2. center tag: for Gmail and Inbox mobile apps and web versions of Gmail, GSuite, Inbox, Yahoo, AOL, Libero, Comcast, freenet, Mail.ru, Orange.fr
+ 3. mso conditional: For Windows 10 Mail
+}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{subject}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{#if title}}
+ {{title}}
+ {{else}}
+ {{subject}}
+ {{/if}}
+
+
+
+
+
+ {{#if username}}
+
{{t "Hi {username}," username=username}}
+ {{/if}}
+
+ {{> @partial-block}}
+
+ {{#if signature}}
+ {{signature}}
+ {{/if}}
+
+
+
+ {{#if action}}
+
+
+ {{> button actionUrl=action.url actionText=action.text}}
+
+
+ {{/if}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{#unless hideNotificationPreferencesLink}}
+
+ {{/unless}}
+
+
+
+
+
+
+
diff --git a/server/core/assets/email-templates/partials/button.hbs b/server/core/assets/email-templates/partials/button.hbs
new file mode 100644
index 000000000..177a1ab46
--- /dev/null
+++ b/server/core/assets/email-templates/partials/button.hbs
@@ -0,0 +1,7 @@
+
diff --git a/server/core/assets/email-templates/password-create/html.hbs b/server/core/assets/email-templates/password-create/html.hbs
new file mode 100644
index 000000000..d17f180ac
--- /dev/null
+++ b/server/core/assets/email-templates/password-create/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "Password creation for your account")}}
+
+ {{{t "Welcome to {instanceName} !" webserverUrl=WEBSERVER.URL instanceName=instanceName}}}
+
+
+ {{t "Your username is: {username}." username=username}}
+
+ {{t "Please click on the link below to set your password (this link will expire within seven days):"}}
+
+ {{> button actionUrl=createPasswordUrl actionText=(t "Create my password")}}
+{{/base}}
diff --git a/server/core/assets/email-templates/password-create/html.pug b/server/core/assets/email-templates/password-create/html.pug
deleted file mode 100644
index d36179208..000000000
--- a/server/core/assets/email-templates/password-create/html.pug
+++ /dev/null
@@ -1,10 +0,0 @@
-extends ../common/greetings
-
-block title
- | Password creation for your account
-
-block content
- p.
- Welcome to #[a(href=WEBSERVER.URL) #{instanceName}]. Your username is: #{username}.
- Please set your password by following #[a(href=createPasswordUrl) this link]: #[a(href=createPasswordUrl) #{createPasswordUrl}]
- (this link will expire within seven days).
diff --git a/server/core/assets/email-templates/password-reset/html.hbs b/server/core/assets/email-templates/password-reset/html.hbs
new file mode 100644
index 000000000..acfdef448
--- /dev/null
+++ b/server/core/assets/email-templates/password-reset/html.hbs
@@ -0,0 +1,15 @@
+{{#> base title=(t "Password reset for your account")}}
+
+ {{t "A reset password procedure for your account has been requested on {instanceName}." username=username instanceName=instanceName}}
+
+
+
+ {{t "Please click on the link below to reset it (the link will expire within 1 hour):"}}
+
+
+ {{> button actionUrl=resetPasswordUrl actionText=(t "Reset my password")}}
+
+
+ {{t "If you are not the person who initiated this request, please let us know by replying to this email."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/password-reset/html.pug b/server/core/assets/email-templates/password-reset/html.pug
deleted file mode 100644
index 2af2885bc..000000000
--- a/server/core/assets/email-templates/password-reset/html.pug
+++ /dev/null
@@ -1,12 +0,0 @@
-extends ../common/greetings
-
-block title
- | Password reset for your account
-
-block content
- p.
- A reset password procedure for your account #{username} has been requested on #[a(href=WEBSERVER.URL) #{instanceName}].
- Please follow #[a(href=resetPasswordUrl) this link] to reset it: #[a(href=resetPasswordUrl) #{resetPasswordUrl}]
- (the link will expire within 1 hour).
- p.
- If you are not the person who initiated this request, please ignore this email.
diff --git a/server/core/assets/email-templates/peertube-version-new/html.hbs b/server/core/assets/email-templates/peertube-version-new/html.hbs
new file mode 100644
index 000000000..930542ae8
--- /dev/null
+++ b/server/core/assets/email-templates/peertube-version-new/html.hbs
@@ -0,0 +1,7 @@
+{{#> base title=(t "New PeerTube version available")}}
+
+ {{t "A new version of PeerTube is available: {latestVersion}." latestVersion=latestVersion}}
+
+ {{{t "You can check the latest news on JoinPeerTube ."}}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/peertube-version-new/html.pug b/server/core/assets/email-templates/peertube-version-new/html.pug
deleted file mode 100644
index 2f4d9399d..000000000
--- a/server/core/assets/email-templates/peertube-version-new/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | New PeerTube version available
-
-block content
- p
- | A new version of PeerTube is available: #{latestVersion}.
- | You can check the latest news on #[a(href="https://joinpeertube.org/news") JoinPeerTube].
diff --git a/server/core/assets/email-templates/plugin-version-new/html.hbs b/server/core/assets/email-templates/plugin-version-new/html.hbs
new file mode 100644
index 000000000..8c2352254
--- /dev/null
+++ b/server/core/assets/email-templates/plugin-version-new/html.hbs
@@ -0,0 +1,14 @@
+{{! New plugin version available }}
+{{#> base title=(t "New plugin version available")}}
+
+ {{#if isPlugin}}
+ {{t "A new version of the plugin {pluginName} is available: {latestVersion}." pluginName=pluginName latestVersion=latestVersion}}
+ {{else}}
+ {{t "A new version of the theme {pluginName} is available: {latestVersion}." pluginName=pluginName latestVersion=latestVersion}}
+ {{/if}}
+
+
+
+ {{{t "You might want to upgrade it on your admin interface ." pluginUrl=pluginUrl}}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/plugin-version-new/html.pug b/server/core/assets/email-templates/plugin-version-new/html.pug
deleted file mode 100644
index 86d3d87e8..000000000
--- a/server/core/assets/email-templates/plugin-version-new/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | New plugin version available
-
-block content
- p
- | A new version of the plugin/theme #{pluginName} is available: #{latestVersion}.
- | You might want to upgrade it on #[a(href=pluginUrl) the PeerTube admin interface].
diff --git a/server/core/assets/email-templates/user-export-completed/html.hbs b/server/core/assets/email-templates/user-export-completed/html.hbs
new file mode 100644
index 000000000..714c022dc
--- /dev/null
+++ b/server/core/assets/email-templates/user-export-completed/html.hbs
@@ -0,0 +1,10 @@
+{{! Your export archive has been created }}
+{{#> base title=(t "Your export archive has been created")}}
+
+ {{t "Your export archive has been created."}}
+
+
+
+ {{{t "You can download it in your account export page ." exportsUrl=exportsUrl}}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/user-export-completed/html.pug b/server/core/assets/email-templates/user-export-completed/html.pug
deleted file mode 100644
index 00cf64211..000000000
--- a/server/core/assets/email-templates/user-export-completed/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | Your export archive has been created
-
-block content
- p
- | Your export archive has been created. You can download it in #[a(href=exportsUrl) your account export page].
diff --git a/server/core/assets/email-templates/user-export-errored/html.hbs b/server/core/assets/email-templates/user-export-errored/html.hbs
new file mode 100644
index 000000000..08490033d
--- /dev/null
+++ b/server/core/assets/email-templates/user-export-errored/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "Failed to create your export archive")}}
+
+ {{t "We are sorry but the generation of your export archive has failed:"}}
+
+
+ {{errorMessage}}
+
+
+ {{t "Please contact your administrator if the problem occurs again."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/user-export-errored/html.pug b/server/core/assets/email-templates/user-export-errored/html.pug
deleted file mode 100644
index 7699a5dd4..000000000
--- a/server/core/assets/email-templates/user-export-errored/html.pug
+++ /dev/null
@@ -1,12 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | Failed to create your export archive
-
-block content
- p
- | We are sorry but the generation of your export archive has failed:
- blockquote !{errorMessage}
- p
- | Please contact your administrator if the problem occurs again.
diff --git a/server/core/assets/email-templates/user-import-completed/html.hbs b/server/core/assets/email-templates/user-import-completed/html.hbs
new file mode 100644
index 000000000..2da267a41
--- /dev/null
+++ b/server/core/assets/email-templates/user-import-completed/html.hbs
@@ -0,0 +1,68 @@
+{{#> base title=(t "Your archive import has finished")}}
+ {{#* inline "displaySummary"}}
+
+ {{#if stats.success}}
+ {{t "Imported: {success}" success=stats.success}}
+ {{/if}}
+ {{#if stats.duplicates}}
+ {{t "Not imported as considered duplicate: {duplicates}" duplicates=stats.duplicates}}
+ {{/if}}
+ {{#if stats.errors}}
+ {{t "Not imported due to error: {errors}" errors=stats.errors}}
+ {{/if}}
+
+ {{/inline}}
+
+ {{t "Your archive import has finished. Here is the summary of imported objects:"}}
+
+
+
+ {{t "User settings:"}}
+ {{> displaySummary stats=resultStats.userSettings}}
+
+
+ {{t "Account (name, description, avatar...):"}}
+ {{> displaySummary stats=resultStats.account}}
+
+
+ {{t "Blocklist:"}}
+ {{> displaySummary stats=resultStats.blocklist}}
+
+
+ {{t "Channels:"}}
+ {{> displaySummary stats=resultStats.channels}}
+
+
+ {{t "Likes:"}}
+ {{> displaySummary stats=resultStats.likes}}
+
+
+ {{t "Dislikes:"}}
+ {{> displaySummary stats=resultStats.dislikes}}
+
+
+ {{t "Subscriptions:"}}
+ {{> displaySummary stats=resultStats.following}}
+
+
+ {{t "Video Playlists:"}}
+ {{> displaySummary stats=resultStats.videoPlaylists}}
+
+
+ {{t "Videos:"}}
+ {{> displaySummary stats=resultStats.videos}}
+
+
+ {{t "Video history:"}}
+ {{> displaySummary stats=resultStats.userVideoHistory}}
+
+
+ {{t "Watched Words Lists:"}}
+ {{> displaySummary stats=resultStats.watchedWordsLists}}
+
+
+ {{t "Comment auto tag policies:"}}
+ {{> displaySummary stats=resultStats.commentAutoTagPolicies}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/user-import-completed/html.pug b/server/core/assets/email-templates/user-import-completed/html.pug
deleted file mode 100644
index ddd6f023d..000000000
--- a/server/core/assets/email-templates/user-import-completed/html.pug
+++ /dev/null
@@ -1,55 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-mixin displaySummary(stats)
- ul
- if stats.success
- li Imported: #{stats.success}
- if stats.duplicates
- li Not imported as considered duplicate: #{stats.duplicates}
- if stats.errors
- li Not imported due to error: #{stats.errors}
-
-block title
- | Your archive import has finished
-
-block content
- p Your archive import has finished. Here is the summary of imported objects:
-
- ul
- li
- strong User settings:
- +displaySummary(resultStats.userSettings)
- li
- strong Account (name, description, avatar...):
- +displaySummary(resultStats.account)
- li
- strong Blocklist:
- +displaySummary(resultStats.blocklist)
- li
- strong Channels:
- +displaySummary(resultStats.channels)
- li
- strong Likes:
- +displaySummary(resultStats.likes)
- li
- strong Dislikes:
- +displaySummary(resultStats.dislikes)
- li
- strong Subscriptions:
- +displaySummary(resultStats.following)
- li
- strong Video Playlists:
- +displaySummary(resultStats.videoPlaylists)
- li
- strong Videos:
- +displaySummary(resultStats.videos)
- li
- strong Video history:
- +displaySummary(resultStats.userVideoHistory)
- li
- strong Watched Words Lists:
- +displaySummary(resultStats.watchedWordsLists)
- li
- strong Comment auto tag policies:
- +displaySummary(resultStats.commentAutoTagPolicies)
diff --git a/server/core/assets/email-templates/user-import-errored/html.hbs b/server/core/assets/email-templates/user-import-errored/html.hbs
new file mode 100644
index 000000000..78ab3e0fb
--- /dev/null
+++ b/server/core/assets/email-templates/user-import-errored/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "Failed to import your archive")}}
+
+ {{t "We are sorry but the import of your archive has failed:"}}
+
+
+ {{errorMessage}}
+
+
+ {{t "Please contact your administrator if the problem occurs again."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/user-import-errored/html.pug b/server/core/assets/email-templates/user-import-errored/html.pug
deleted file mode 100644
index 8f5041d1e..000000000
--- a/server/core/assets/email-templates/user-import-errored/html.pug
+++ /dev/null
@@ -1,12 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | Failed to import your archive
-
-block content
- p
- | We are sorry but the import of your archive has failed:
- blockquote !{errorMessage}
- p
- | Please contact your administrator if the problem occurs again.
diff --git a/server/core/assets/email-templates/user-registered/html.hbs b/server/core/assets/email-templates/user-registered/html.hbs
new file mode 100644
index 000000000..2493f1834
--- /dev/null
+++ b/server/core/assets/email-templates/user-registered/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "A new user registered")}}
+
+ {{{t "User {userUsername} just registered." accountUrl=accountUrl userUsername=user.username}}}
+
+ {{#if userEmail}}
+ {{{t "You might want to contact them at {userEmail} ." userEmail=userEmail}}}
+ {{else}}
+ {{{t "You might want to contact them at {userEmail} (the email has not been verified yet)." userEmail=userPendingEmail}}}
+ {{/if}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/user-registered/html.pug b/server/core/assets/email-templates/user-registered/html.pug
deleted file mode 100644
index 20f62125e..000000000
--- a/server/core/assets/email-templates/user-registered/html.pug
+++ /dev/null
@@ -1,10 +0,0 @@
-extends ../common/greetings
-
-block title
- | A new user registered
-
-block content
- - var mail = user.email || user.pendingEmail;
- p
- | User #[a(href=`${WEBSERVER.URL}/accounts/${user.username}`) #{user.username}] just registered.
- | You might want to contact them at #[a(href=`mailto:${mail}`) #{mail}].
\ No newline at end of file
diff --git a/server/core/assets/email-templates/user-registration-request-accepted/html.hbs b/server/core/assets/email-templates/user-registration-request-accepted/html.hbs
new file mode 100644
index 000000000..8141a6425
--- /dev/null
+++ b/server/core/assets/email-templates/user-registration-request-accepted/html.hbs
@@ -0,0 +1,11 @@
+{{#> base title=(t "Congratulation {username}, your registration request has been accepted!" username=username)}}
+
+ {{t "Your registration request has been accepted."}}
+
+
+
+ {{t "Moderators sent you the following message:"}}
+
+
+ {{moderationResponse}}
+{{/base}}
diff --git a/server/core/assets/email-templates/user-registration-request-accepted/html.pug b/server/core/assets/email-templates/user-registration-request-accepted/html.pug
deleted file mode 100644
index 7a52c3fe1..000000000
--- a/server/core/assets/email-templates/user-registration-request-accepted/html.pug
+++ /dev/null
@@ -1,10 +0,0 @@
-extends ../common/greetings
-
-block title
- | Congratulation #{username}, your registration request has been accepted!
-
-block content
- p Your registration request has been accepted.
- p Moderators sent you the following message:
- blockquote(style='white-space: pre-wrap') #{moderationResponse}
- p Your account has been created and you can login on #[a(href=loginLink) #{loginLink}]
diff --git a/server/core/assets/email-templates/user-registration-request-rejected/html.hbs b/server/core/assets/email-templates/user-registration-request-rejected/html.hbs
new file mode 100644
index 000000000..1b537ba9e
--- /dev/null
+++ b/server/core/assets/email-templates/user-registration-request-rejected/html.hbs
@@ -0,0 +1,7 @@
+{{#> base title=(t "Registration request of your account {username} has rejected" username=username)}}
+ {{t "Your registration request has been rejected." }}
+
+ {{t "Moderators sent you the following message:" }}
+
+ {{moderationResponse}}
+{{/base}}
diff --git a/server/core/assets/email-templates/user-registration-request-rejected/html.pug b/server/core/assets/email-templates/user-registration-request-rejected/html.pug
deleted file mode 100644
index ec0aa8dfe..000000000
--- a/server/core/assets/email-templates/user-registration-request-rejected/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | Registration request of your account #{username} has rejected
-
-block content
- p Your registration request has been rejected.
- p Moderators sent you the following message:
- blockquote(style='white-space: pre-wrap') #{moderationResponse}
diff --git a/server/core/assets/email-templates/user-registration-request/html.hbs b/server/core/assets/email-templates/user-registration-request/html.hbs
new file mode 100644
index 000000000..610b4d45b
--- /dev/null
+++ b/server/core/assets/email-templates/user-registration-request/html.hbs
@@ -0,0 +1,7 @@
+{{#> base title=(t "A new user wants to register")}}
+
+ {{t "User {registrationUsername} wants to register on {instanceName} for the following reason:" registrationUsername=registration.username instanceName=instanceName}}
+
+
+ {{registration.registrationReason}}
+{{/base}}
diff --git a/server/core/assets/email-templates/user-registration-request/html.pug b/server/core/assets/email-templates/user-registration-request/html.pug
deleted file mode 100644
index 64898f3f2..000000000
--- a/server/core/assets/email-templates/user-registration-request/html.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-extends ../common/greetings
-
-block title
- | A new user wants to register
-
-block content
- p User #{registration.username} wants to register on your PeerTube instance with the following reason:
- blockquote(style='white-space: pre-wrap') #{registration.registrationReason}
- p You can accept or reject the registration request in the #[a(href=`${WEBSERVER.URL}/admin/moderation/registrations/list`) administration].
diff --git a/server/core/assets/email-templates/verify-registration-email/html.hbs b/server/core/assets/email-templates/verify-registration-email/html.hbs
new file mode 100644
index 000000000..9d811f4ca
--- /dev/null
+++ b/server/core/assets/email-templates/verify-registration-email/html.hbs
@@ -0,0 +1,19 @@
+{{#> base title=(t "Email verification")}}
+ {{#if isRegistrationRequest}}
+ {{{t "You requested an account on {instanceName} ." webserverUrl=WEBSERVER.URL instanceName=instanceName}}}
+ {{t "To complete your registration request you must verify your email first!"}}
+ {{else}}
+ {{{t "You created an account on {instanceName} ." webserverUrl=WEBSERVER.URL instanceName=instanceName}}}
+ {{t "To start using your account you must verify your email first!"}}
+ {{/if}}
+
+
+ {{t "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):"}}
+
+
+ {{> button actionUrl=verifyEmailUrl actionText=(t "Verify my email")}}
+
+
+ {{t "If you are not the person who initiated this request, please let us know by replying to this email."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/verify-registration-email/html.pug b/server/core/assets/email-templates/verify-registration-email/html.pug
deleted file mode 100644
index c5c2fa91f..000000000
--- a/server/core/assets/email-templates/verify-registration-email/html.pug
+++ /dev/null
@@ -1,16 +0,0 @@
-extends ../common/greetings
-
-block title
- | Email verification
-
-block content
- if isRegistrationRequest
- p You requested an account on #[a(href=WEBSERVER.URL) #{instanceName}].
- p To complete your registration request you must verify your email first!
- else
- p You created an account on #[a(href=WEBSERVER.URL) #{instanceName}].
- p To start using your account you must verify your email first!
-
- p Please follow #[a(href=verifyEmailUrl) this link] to verify this email belongs to you.
- p If you can't see the verification link above you can use the following link #[a(href=verifyEmailUrl) #{verifyEmailUrl}]
- p If you are not the person who initiated this request, please ignore this email.
diff --git a/server/core/assets/email-templates/verify-user-change-email/html.hbs b/server/core/assets/email-templates/verify-user-change-email/html.hbs
new file mode 100644
index 000000000..8909fb1cb
--- /dev/null
+++ b/server/core/assets/email-templates/verify-user-change-email/html.hbs
@@ -0,0 +1,13 @@
+{{#> base title=(t "Email verification")}}
+ {{t "You requested to change your email."}}
+
+
+ {{t "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):"}}
+
+
+ {{> button actionUrl=verifyEmailUrl actionText=(t "Verify my email")}}
+
+
+ {{t "If you are not the person who initiated this request, please let us know by replying to this email."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/verify-user-change-email/html.pug b/server/core/assets/email-templates/verify-user-change-email/html.pug
deleted file mode 100644
index c5b18662d..000000000
--- a/server/core/assets/email-templates/verify-user-change-email/html.pug
+++ /dev/null
@@ -1,11 +0,0 @@
-extends ../common/greetings
-
-block title
- | Email verification
-
-block content
- p You requested to change your email.
-
- p Please follow #[a(href=verifyEmailUrl) this link] to verify this email belongs to you.
- p If you can't see the verification link above you can use the following link #[a(href=verifyEmailUrl) #{verifyEmailUrl}]
- p If you are not the person who initiated this request, please contact your administrator.
diff --git a/server/core/assets/email-templates/video-abuse-new/html.hbs b/server/core/assets/email-templates/video-abuse-new/html.hbs
new file mode 100644
index 000000000..bc203b36d
--- /dev/null
+++ b/server/core/assets/email-templates/video-abuse-new/html.hbs
@@ -0,0 +1,27 @@
+{{#> base title=(t "A video is pending moderation")}}
+
+ {{#if isLocal}}
+ {{{t "{instanceName} received an abuse report for the video {videoName} ." instanceName=instanceName videoUrl=videoUrl videoName=videoName}}}
+ {{else}}
+ {{{t "{instanceName} received an abuse report for the remote video {videoName} ." instanceName=instanceName videoUrl=videoUrl videoName=videoName}}}
+ {{/if}}
+
+
+
+ {{{t "The video was uploaded by {channelDisplayName} channel." channelUrl=channelUrl channelDisplayName=channelDisplayName}}}
+
+
+
+ {{#if videoPublishedAt}}
+ {{t "It was published on {videoPublishedAt}." videoPublishedAt=videoPublishedAt}}
+ {{else}}
+ {{t "It was uploaded on {videoCreatedAt} but not yet published." videoCreatedAt=videoCreatedAt}}
+ {{/if}}
+
+
+ {{t "The reporter, {reporter}, cited the following reason(s):" reporter=reporter}}
+
+ {{reason}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-abuse-new/html.pug b/server/core/assets/email-templates/video-abuse-new/html.pug
deleted file mode 100644
index a085b4b38..000000000
--- a/server/core/assets/email-templates/video-abuse-new/html.pug
+++ /dev/null
@@ -1,18 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | A video is pending moderation
-
-block content
- p
- | #[a(href=WEBSERVER.URL) #{instanceName}] received an abuse report for the #{isLocal ? '' : 'remote '}video "
- a(href=videoUrl) #{videoName}
- | " by #[+channel(videoChannel)]
- if videoPublishedAt
- | , published the #{videoPublishedAt}.
- else
- | , uploaded the #{videoCreatedAt} but not yet published.
- p The reporter, #{reporter}, cited the following reason(s):
- blockquote #{reason}
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/video-auto-blacklist-new/html.hbs b/server/core/assets/email-templates/video-auto-blacklist-new/html.hbs
new file mode 100644
index 000000000..93fc88781
--- /dev/null
+++ b/server/core/assets/email-templates/video-auto-blacklist-new/html.hbs
@@ -0,0 +1,13 @@
+{{#> base title=(t "A video is pending moderation")}}
+
+ {{{t "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} ." videoUrl=videoUrl videoName=videoName channelUrl=channelUrl channelDisplayName=channelDisplayName}}}
+
+
+
+ {{t "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it."}}
+
+
+
+ {{t "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public."}}
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-auto-blacklist-new/html.pug b/server/core/assets/email-templates/video-auto-blacklist-new/html.pug
deleted file mode 100644
index 07c8dfd16..000000000
--- a/server/core/assets/email-templates/video-auto-blacklist-new/html.pug
+++ /dev/null
@@ -1,17 +0,0 @@
-extends ../common/greetings
-include ../common/mixins
-
-block title
- | A video is pending moderation
-
-block content
- p
- | A recently added video was auto-blacklisted and requires moderator review before going public:
- |
- a(href=videoUrl) #{videoName}
- |
- | by #[+channel(channel)].
- p.
- Apart from the publisher and the moderation team, no one will be able to see the video until you
- unblacklist it. If you trust the publisher, any admin can whitelist the user for later videos so
- that they don't require approval before going public.
diff --git a/server/core/assets/email-templates/video-comment-abuse-new/html.hbs b/server/core/assets/email-templates/video-comment-abuse-new/html.hbs
new file mode 100644
index 000000000..6841ba3c9
--- /dev/null
+++ b/server/core/assets/email-templates/video-comment-abuse-new/html.hbs
@@ -0,0 +1,21 @@
+{{#> base title=(t "A comment is pending moderation")}}
+
+ {{#if isLocal}}
+ {{{t "{instanceName} received an abuse report for the comment on video {videoName} ." instanceName=instanceName commentUrl=commentUrl videoName=videoName}}}
+ {{else}}
+ {{{t "{instanceName} received an abuse report for the remote comment on video {videoName} ." instanceName=instanceName commentUrl=commentUrl videoName=videoName}}}
+ {{/if}}
+
+
+
+ {{t "The comment was posted on {commentCreatedAt} by {flaggedAccount} ." commentCreatedAt=commentCreatedAt flaggedAccount=flaggedAccount}}
+
+
+
+ {{t "The reporter, {reporter}, cited the following reason(s):" reporter=reporter}}
+
+
+ {{reason}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-comment-abuse-new/html.pug b/server/core/assets/email-templates/video-comment-abuse-new/html.pug
deleted file mode 100644
index 752bf7c10..000000000
--- a/server/core/assets/email-templates/video-comment-abuse-new/html.pug
+++ /dev/null
@@ -1,16 +0,0 @@
-extends ../common/greetings
-include ../common/mixins.pug
-
-block title
- | A comment is pending moderation
-
-block content
- p
- | #[a(href=WEBSERVER.URL) #{instanceName}] received an abuse report for the #{isLocal ? '' : 'remote '}
- a(href=commentUrl) comment on video "#{videoName}"
- | of #{flaggedAccount}
- | created on #{commentCreatedAt}
-
- p The reporter, #{reporter}, cited the following reason(s):
- blockquote #{reason}
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/video-comment-mention/html.hbs b/server/core/assets/email-templates/video-comment-mention/html.hbs
new file mode 100644
index 000000000..215091356
--- /dev/null
+++ b/server/core/assets/email-templates/video-comment-mention/html.hbs
@@ -0,0 +1,9 @@
+{{#> base title=(t "Someone mentioned you")}}
+
+ {{{t "{accountName} mentioned you in a comment on video {videoName} :" accountUrl=accountUrl handle=handle accountName=accountName videoUrl=videoUrl videoName=video.name}}}
+
+
+ {{{commentHtml}}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-comment-mention/html.pug b/server/core/assets/email-templates/video-comment-mention/html.pug
deleted file mode 100644
index a34c6b090..000000000
--- a/server/core/assets/email-templates/video-comment-mention/html.pug
+++ /dev/null
@@ -1,11 +0,0 @@
-extends ../common/greetings
-
-block title
- | Someone mentioned you
-
-block content
- p.
- #[a(href=accountUrl title=handle) #{accountName}] mentioned you in a comment on video
- "#[a(href=videoUrl) #{video.name}]":
- blockquote !{commentHtml}
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/video-comment-new/html.hbs b/server/core/assets/email-templates/video-comment-new/html.hbs
new file mode 100644
index 000000000..af78d028e
--- /dev/null
+++ b/server/core/assets/email-templates/video-comment-new/html.hbs
@@ -0,0 +1,13 @@
+{{#> base title=(t "Someone commented your video")}}
+
+ {{{t "{accountName} added a comment on your video {videoName} :" accountUrl=accountUrl handle=handle accountName=accountName videoUrl=videoUrl videoName=video.name}}}
+
+
+ {{{commentHtml}}}
+
+ {{#if requiresApproval}}
+ {{t "This comment requires approval."}}
+ {{/if}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-comment-new/html.pug b/server/core/assets/email-templates/video-comment-new/html.pug
deleted file mode 100644
index a11787026..000000000
--- a/server/core/assets/email-templates/video-comment-new/html.pug
+++ /dev/null
@@ -1,16 +0,0 @@
-extends ../common/greetings
-
-block title
- | Someone commented your video
-
-block content
- p.
- #[a(href=accountUrl title=handle) #{accountName}] added a comment on your video
- "#[a(href=videoUrl) #{video.name}]":
-
- blockquote !{commentHtml}
-
- if requiresApproval
- | This comment requires approval.
-
- br(style="display: none;")
diff --git a/server/core/assets/email-templates/video-owner-blacklist-new/html.hbs b/server/core/assets/email-templates/video-owner-blacklist-new/html.hbs
new file mode 100644
index 000000000..f40d99209
--- /dev/null
+++ b/server/core/assets/email-templates/video-owner-blacklist-new/html.hbs
@@ -0,0 +1,15 @@
+{{#> base title=(t "Your video has been blocked")}}
+
+ {{#if reason}}
+ {{{t "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:" videoName=videoName instanceName=instanceName}}}
+ {{else}}
+ {{{t "Your video {videoName} has been blocked by {instanceName} moderators." videoName=videoName instanceName=instanceName}}}
+ {{/if}}
+
+
+ {{#if reason}}
+ {{reason}}
+ {{/if}}
+
+
+{{/base}}
diff --git a/server/core/assets/email-templates/video-owner-unblacklist/html.hbs b/server/core/assets/email-templates/video-owner-unblacklist/html.hbs
new file mode 100644
index 000000000..a75ce66e1
--- /dev/null
+++ b/server/core/assets/email-templates/video-owner-unblacklist/html.hbs
@@ -0,0 +1,5 @@
+{{#> base title=(t "Your video has been unblocked")}}
+
+ {{{t "Your video {videoName} has been unblocked by {instanceName} moderators." videoName=videoName instanceName=instanceName}}}
+
+{{/base}}
diff --git a/server/core/controllers/api/client-config.ts b/server/core/controllers/api/client-config.ts
new file mode 100644
index 000000000..14675a0a4
--- /dev/null
+++ b/server/core/controllers/api/client-config.ts
@@ -0,0 +1,36 @@
+import { is18nLocale } from '@peertube/peertube-core-utils'
+import { HttpStatusCode } from '@peertube/peertube-models'
+import { setClientLanguageCookie } from '@server/helpers/i18n.js'
+import express from 'express'
+import { apiRateLimiter } from '../../middlewares/index.js'
+
+const clientConfigRouter = express.Router()
+
+clientConfigRouter.use(apiRateLimiter)
+
+clientConfigRouter.post(
+ '/update-interface-language',
+ updateLanguage
+)
+
+// ---------------------------------------------------------------------------
+
+export {
+ clientConfigRouter
+}
+
+// ---------------------------------------------------------------------------
+
+function updateLanguage (req: express.Request, res: express.Response) {
+ const language = req.body.language
+
+ if (language !== null && !is18nLocale(language)) {
+ return res.fail({
+ message: req.t('{language} is not a valid language', { language })
+ })
+ }
+
+ setClientLanguageCookie(res, language)
+
+ return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
+}
diff --git a/server/core/controllers/api/config.ts b/server/core/controllers/api/config.ts
index f55540a5c..2656b023a 100644
--- a/server/core/controllers/api/config.ts
+++ b/server/core/controllers/api/config.ts
@@ -309,6 +309,8 @@ function customConfig (): CustomConfig {
businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
hardwareInformation: CONFIG.INSTANCE.HARDWARE_INFORMATION,
+ defaultLanguage: CONFIG.INSTANCE.DEFAULT_LANGUAGE,
+
languages: CONFIG.INSTANCE.LANGUAGES,
categories: CONFIG.INSTANCE.CATEGORIES,
diff --git a/server/core/controllers/api/index.ts b/server/core/controllers/api/index.ts
index d5034c1de..437151f27 100644
--- a/server/core/controllers/api/index.ts
+++ b/server/core/controllers/api/index.ts
@@ -7,6 +7,7 @@ import { accountsRouter } from './accounts.js'
import { automaticTagRouter } from './automatic-tags.js'
import { blocklistRouter } from './blocklist.js'
import { bulkRouter } from './bulk.js'
+import { clientConfigRouter } from './client-config.js'
import { configRouter } from './config.js'
import { customPageRouter } from './custom-page.js'
import { jobsRouter } from './jobs.js'
@@ -53,6 +54,7 @@ apiRouter.use('/blocklist', blocklistRouter)
apiRouter.use('/runners', runnersRouter)
apiRouter.use('/watched-words', watchedWordsRouter)
apiRouter.use('/automatic-tags', automaticTagRouter)
+apiRouter.use('/client-config', clientConfigRouter)
apiRouter.use('/ping', pong)
apiRouter.use('/*', badRequest)
diff --git a/server/core/controllers/api/server/contact.ts b/server/core/controllers/api/server/contact.ts
index 53e73fa2b..29250193f 100644
--- a/server/core/controllers/api/server/contact.ts
+++ b/server/core/controllers/api/server/contact.ts
@@ -7,15 +7,12 @@ import { asyncMiddleware, contactAdministratorValidator } from '../../../middlew
const contactRouter = express.Router()
-contactRouter.post('/contact',
- asyncMiddleware(contactAdministratorValidator),
- asyncMiddleware(contactAdministrator)
-)
+contactRouter.post('/contact', asyncMiddleware(contactAdministratorValidator), asyncMiddleware(contactAdministrator))
async function contactAdministrator (req: express.Request, res: express.Response) {
const data = req.body as ContactForm
- Emailer.Instance.addContactFormJob(data.fromEmail, data.fromName, data.subject, data.body)
+ Emailer.Instance.addContactFormJob({ fromEmail: data.fromEmail, fromName: data.fromName, subject: data.subject, body: data.body })
try {
await Redis.Instance.setContactFormIp(req.ip)
diff --git a/server/core/controllers/api/server/debug.ts b/server/core/controllers/api/server/debug.ts
index 5ecf21d6b..d49395238 100644
--- a/server/core/controllers/api/server/debug.ts
+++ b/server/core/controllers/api/server/debug.ts
@@ -1,26 +1,41 @@
-import express from 'express'
-import { Debug, HttpStatusCode, SendDebugCommand, UserRight } from '@peertube/peertube-models'
+import {
+ Debug,
+ HttpStatusCode,
+ SendDebugCommand,
+ SendDebugTestEmails,
+ UserExportState,
+ UserImportResultSummary,
+ UserRegistrationState,
+ UserRight
+} from '@peertube/peertube-models'
+import { logger } from '@server/helpers/logger.js'
+import { CONFIG } from '@server/initializers/config.js'
+import { WEBSERVER } from '@server/initializers/constants.js'
import { InboxManager } from '@server/lib/activitypub/inbox-manager.js'
+import { Emailer } from '@server/lib/emailer.js'
import { RemoveDanglingResumableUploadsScheduler } from '@server/lib/schedulers/remove-dangling-resumable-uploads-scheduler.js'
+import { RemoveExpiredUserExportsScheduler } from '@server/lib/schedulers/remove-expired-user-exports-scheduler.js'
import { UpdateVideosScheduler } from '@server/lib/schedulers/update-videos-scheduler.js'
import { VideoChannelSyncLatestScheduler } from '@server/lib/schedulers/video-channel-sync-latest-scheduler.js'
import { VideoViewsBufferScheduler } from '@server/lib/schedulers/video-views-buffer-scheduler.js'
import { VideoViewsManager } from '@server/lib/views/video-views-manager.js'
-import { authenticate, ensureUserHasRight } from '../../../middlewares/index.js'
-import { RemoveExpiredUserExportsScheduler } from '@server/lib/schedulers/remove-expired-user-exports-scheduler.js'
+import express from 'express'
+import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares/index.js'
const debugRouter = express.Router()
-debugRouter.get('/debug',
+debugRouter.get(
+ '/debug',
authenticate,
ensureUserHasRight(UserRight.MANAGE_DEBUG),
getDebug
)
-debugRouter.post('/debug/run-command',
+debugRouter.post(
+ '/debug/run-command',
authenticate,
ensureUserHasRight(UserRight.MANAGE_DEBUG),
- runCommand
+ asyncMiddleware(runCommand)
)
// ---------------------------------------------------------------------------
@@ -47,7 +62,8 @@ async function runCommand (req: express.Request, res: express.Response) {
'process-video-views-buffer': () => VideoViewsBufferScheduler.Instance.execute(),
'process-video-viewers': () => VideoViewsManager.Instance.processViewerStats(),
'process-update-videos-scheduler': () => UpdateVideosScheduler.Instance.execute(),
- 'process-video-channel-sync-latest': () => VideoChannelSyncLatestScheduler.Instance.execute()
+ 'process-video-channel-sync-latest': () => VideoChannelSyncLatestScheduler.Instance.execute(),
+ 'test-emails': () => testEmails(req, res)
}
if (!processors[body.command]) {
@@ -58,3 +74,114 @@ async function runCommand (req: express.Request, res: express.Response) {
return res.status(HttpStatusCode.NO_CONTENT_204).end()
}
+
+// ---------------------------------------------------------------------------
+// Private
+// ---------------------------------------------------------------------------
+
+async function testEmails (req: express.Request, res: express.Response) {
+ const email = (req.body as SendDebugTestEmails).email
+
+ if (!email) {
+ return res.fail({ message: 'Email is required for test-emails command' })
+ }
+
+ if (!email.includes('@')) {
+ return res.fail({ message: 'Invalid email format for test-emails command' })
+ }
+
+ const fakeUrl = WEBSERVER.URL + '/test'
+ const language = CONFIG.INSTANCE.DEFAULT_LANGUAGE
+ const to = { email, language }
+
+ Emailer.Instance.addPasswordResetEmailJob({ username: 'test-username', to: email, language, resetPasswordUrl: fakeUrl })
+ Emailer.Instance.addPasswordCreateEmailJob({ username: 'test-username', to: email, language, createPasswordUrl: fakeUrl })
+ Emailer.Instance.addUserVerifyChangeEmailJob({ username: 'test-username', to: email, language, verifyEmailUrl: fakeUrl })
+
+ {
+ Emailer.Instance.addRegistrationVerifyEmailJob({
+ username: 'test-username',
+ isRegistrationRequest: true,
+ to: email,
+ language,
+ verifyEmailUrl: fakeUrl
+ })
+ Emailer.Instance.addRegistrationVerifyEmailJob({
+ username: 'test-username',
+ isRegistrationRequest: false,
+ to: email,
+ language,
+ verifyEmailUrl: fakeUrl
+ })
+ }
+
+ {
+ const user = { username: 'test-username', email, language }
+
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: true, reason: 'Test reason for blocking' })
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: false, reason: 'Test reason for blocking' })
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: true })
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: false })
+ }
+
+ Emailer.Instance.addContactFormJob({ body: 'test contact form', fromEmail: email, fromName: 'Test User', subject: 'Test Subject' })
+
+ {
+ Emailer.Instance.addUserRegistrationRequestProcessedJob({
+ username: 'test-username',
+ state: UserRegistrationState.ACCEPTED,
+ email,
+ moderationResponse: 'Test moderation response'
+ })
+ Emailer.Instance.addUserRegistrationRequestProcessedJob({
+ username: 'test-username',
+ state: UserRegistrationState.REJECTED,
+ email,
+ moderationResponse: 'Test moderation response'
+ })
+ }
+
+ {
+ await Emailer.Instance.addUserExportCompletedOrErroredJob({ error: 'error', state: UserExportState.ERRORED, userId: 1 }, to)
+ await Emailer.Instance.addUserExportCompletedOrErroredJob({ error: null, state: UserExportState.COMPLETED, userId: 1 }, to)
+ }
+
+ await Emailer.Instance.addUserImportErroredJob({ error: 'Test error', userId: 1 }, to)
+
+ {
+ const summary = {
+ success: 1,
+ duplicates: 2,
+ errors: 3
+ }
+ const resultSummary: UserImportResultSummary = {
+ stats: {
+ blocklist: summary,
+ channels: summary,
+ likes: summary,
+ dislikes: summary,
+ following: summary,
+ videoPlaylists: summary,
+ videos: summary,
+ account: summary,
+ userSettings: summary,
+ userVideoHistory: summary,
+ watchedWordsLists: summary,
+ commentAutoTagPolicies: summary
+ }
+ }
+
+ await Emailer.Instance.addUserImportSuccessJob({ resultSummary, userId: 1 }, to)
+ }
+
+ {
+ const user = { username: 'test-username', email, language }
+
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: true, reason: 'Test reason for blocking' })
+ Emailer.Instance.addUserBlockJob({ ...user, blocked: false })
+ }
+
+ logger.info(`Sent test email to ${email}`)
+
+ return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
+}
diff --git a/server/core/controllers/api/users/index.ts b/server/core/controllers/api/users/index.ts
index 045c093b1..c0bfad58c 100644
--- a/server/core/controllers/api/users/index.ts
+++ b/server/core/controllers/api/users/index.ts
@@ -1,6 +1,7 @@
import { pick } from '@peertube/peertube-core-utils'
import { HttpStatusCode, UserCreate, UserCreateResult, UserRight, UserUpdate } from '@peertube/peertube-models'
import { tokensRouter } from '@server/controllers/api/users/token.js'
+import { getResetPasswordUrl } from '@server/lib/client-urls.js'
import { Hooks } from '@server/lib/plugins/hooks.js'
import { OAuthTokenModel } from '@server/models/oauth/oauth-token.js'
import { MUserAccountDefault } from '@server/types/models/index.js'
@@ -8,7 +9,6 @@ import express from 'express'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger.js'
import { logger, loggerTagsFactory } from '../../../helpers/logger.js'
import { generateRandomString, getFormattedObjects } from '../../../helpers/utils.js'
-import { WEBSERVER } from '../../../initializers/constants.js'
import { sequelizeTypescript } from '../../../initializers/database.js'
import { Emailer } from '../../../lib/emailer.js'
import { Redis } from '../../../lib/redis.js'
@@ -161,11 +161,17 @@ async function createUser (req: express.Request, res: express.Response) {
logger.info('User %s with its channel and account created.', body.username, lTags(user.username))
if (createPassword) {
- // this will send an email for newly created users, so then can set their first password.
+ // This will send an email for newly created users, so then can set their first password
logger.info('Sending to user %s a create password email', body.username, lTags(user.username))
+
const verificationString = await Redis.Instance.setCreatePasswordVerificationString(user.id)
- const url = WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
- Emailer.Instance.addPasswordCreateEmailJob(userToCreate.username, user.email, url)
+
+ Emailer.Instance.addPasswordCreateEmailJob({
+ username: userToCreate.username,
+ to: user.email,
+ language: user.getLanguage(),
+ createPasswordUrl: getResetPasswordUrl(user, verificationString)
+ })
}
Hooks.runAction('action:api.user.created', { body, user, account, videoChannel, req, res })
@@ -289,8 +295,12 @@ async function askResetUserPassword (req: express.Request, res: express.Response
const user = res.locals.user
const verificationString = await Redis.Instance.setResetPasswordVerificationString(user.id)
- const url = WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
- Emailer.Instance.addPasswordResetEmailJob(user.username, user.email, url)
+ Emailer.Instance.addPasswordResetEmailJob({
+ username: user.username,
+ to: user.email,
+ language: user.getLanguage(),
+ resetPasswordUrl: getResetPasswordUrl(user, verificationString)
+ })
logger.info(`User ${user.username} asked password reset.`, lTags(user.username))
@@ -321,7 +331,7 @@ async function changeUserBlock (res: express.Response, user: MUserAccountDefault
await user.save({ transaction: t })
})
- Emailer.Instance.addUserBlockJob(user, block, reason)
+ Emailer.Instance.addUserBlockJob({ username: user.username, email: user.email, language: user.getLanguage(), blocked: block, reason })
auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
}
diff --git a/server/core/controllers/api/users/me.ts b/server/core/controllers/api/users/me.ts
index fcf7e038b..4493e0cd1 100644
--- a/server/core/controllers/api/users/me.ts
+++ b/server/core/controllers/api/users/me.ts
@@ -278,6 +278,7 @@ async function updateMe (req: express.Request, res: express.Response) {
'autoPlayNextVideoPlaylist',
'videosHistoryEnabled',
'videoLanguages',
+ 'language',
'theme',
'noInstanceConfigWarningModal',
'noAccountSetupWarningModal',
diff --git a/server/core/controllers/client.ts b/server/core/controllers/client.ts
index 4105a0309..7fe5c10dd 100644
--- a/server/core/controllers/client.ts
+++ b/server/core/controllers/client.ts
@@ -208,10 +208,10 @@ async function generateActorHtmlPage (req: express.Request, res: express.Respons
async function generateManifest (req: express.Request, res: express.Response) {
const serverActor = await getServerActor()
- const defaultIcons = [ 36, 48, 72, 96, 144, 192, 512 ].map(size => {
+ const defaultIcons = [ 192, 512 ].map(size => {
return {
src: `/client/assets/images/icons/icon-${size}x${size}.png`,
- sizes: `36x36`,
+ sizes: `${size}x${size}`,
type: 'image/png'
}
})
diff --git a/server/core/controllers/feeds/shared/common-feed-utils.ts b/server/core/controllers/feeds/shared/common-feed-utils.ts
index 8866adb8a..31726c8d3 100644
--- a/server/core/controllers/feeds/shared/common-feed-utils.ts
+++ b/server/core/controllers/feeds/shared/common-feed-utils.ts
@@ -117,7 +117,7 @@ export async function buildFeedMetadata (options: {
}) {
const { video, videoChannel, account } = options
- let imageUrl = WEBSERVER.URL + '/client/assets/images/icons/icon-96x96.png'
+ let imageUrl = ServerConfigManager.Instance.getLogoUrl(await getServerActor(), 512)
let ownerImageUrl: string
let name: string
let description: string
diff --git a/server/core/helpers/custom-validators/users.ts b/server/core/helpers/custom-validators/users.ts
index 84c49ff66..e609e2f2b 100644
--- a/server/core/helpers/custom-validators/users.ts
+++ b/server/core/helpers/custom-validators/users.ts
@@ -1,125 +1,104 @@
-import validator from 'validator'
+import { AVAILABLE_LOCALES } from '@peertube/peertube-core-utils'
import { UserRole } from '@peertube/peertube-models'
+import validator from 'validator'
import { isEmailEnabled } from '../../initializers/config.js'
import { CONSTRAINTS_FIELDS, NSFW_POLICY_TYPES } from '../../initializers/constants.js'
import { exists, isArray, isBooleanValid } from './misc.js'
const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS
-function isUserPasswordValid (value: string) {
+export function isUserPasswordValid (value: string) {
return validator.default.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD)
}
-function isUserPasswordValidOrEmpty (value: string) {
+export function isUserPasswordValidOrEmpty (value: string) {
// Empty password is only possible if emailing is enabled.
if (value === '') return isEmailEnabled()
return isUserPasswordValid(value)
}
-function isUserVideoQuotaValid (value: string) {
+export function isUserVideoQuotaValid (value: string) {
return exists(value) && validator.default.isInt(value + '', USERS_CONSTRAINTS_FIELDS.VIDEO_QUOTA)
}
-function isUserVideoQuotaDailyValid (value: string) {
+export function isUserVideoQuotaDailyValid (value: string) {
return exists(value) && validator.default.isInt(value + '', USERS_CONSTRAINTS_FIELDS.VIDEO_QUOTA_DAILY)
}
-function isUserUsernameValid (value: string) {
+export function isUserUsernameValid (value: string) {
return exists(value) &&
validator.default.matches(value, new RegExp(`^[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?$`)) &&
validator.default.isLength(value, USERS_CONSTRAINTS_FIELDS.USERNAME)
}
-function isUserDisplayNameValid (value: string) {
+export function isUserDisplayNameValid (value: string) {
return value === null || (exists(value) && validator.default.isLength(value, CONSTRAINTS_FIELDS.USERS.NAME))
}
-function isUserDescriptionValid (value: string) {
+export function isUserDescriptionValid (value: string) {
return value === null || (exists(value) && validator.default.isLength(value, CONSTRAINTS_FIELDS.USERS.DESCRIPTION))
}
-function isUserEmailVerifiedValid (value: any) {
+export function isUserEmailVerifiedValid (value: any) {
return isBooleanValid(value)
}
const nsfwPolicies = new Set(Object.values(NSFW_POLICY_TYPES))
-function isUserNSFWPolicyValid (value: any) {
+export function isUserNSFWPolicyValid (value: any) {
return exists(value) && nsfwPolicies.has(value)
}
-function isUserP2PEnabledValid (value: any) {
+export function isUserP2PEnabledValid (value: any) {
return isBooleanValid(value)
}
-function isUserVideosHistoryEnabledValid (value: any) {
+export function isUserVideosHistoryEnabledValid (value: any) {
return isBooleanValid(value)
}
-function isUserAutoPlayVideoValid (value: any) {
+export function isUserAutoPlayVideoValid (value: any) {
return isBooleanValid(value)
}
-function isUserVideoLanguages (value: any) {
+export function isUserVideoLanguages (value: any) {
return value === null || (isArray(value) && value.length < CONSTRAINTS_FIELDS.USERS.VIDEO_LANGUAGES.max)
}
-function isUserAdminFlagsValid (value: any) {
+export function isUserLanguage (value: any) {
+ return value === null || AVAILABLE_LOCALES.includes(value)
+}
+
+export function isUserAdminFlagsValid (value: any) {
return exists(value) && validator.default.isInt('' + value)
}
-function isUserBlockedValid (value: any) {
+export function isUserBlockedValid (value: any) {
return isBooleanValid(value)
}
-function isUserAutoPlayNextVideoValid (value: any) {
+export function isUserAutoPlayNextVideoValid (value: any) {
return isBooleanValid(value)
}
-function isUserAutoPlayNextVideoPlaylistValid (value: any) {
+export function isUserAutoPlayNextVideoPlaylistValid (value: any) {
return isBooleanValid(value)
}
-function isUserEmailPublicValid (value: any) {
+export function isUserEmailPublicValid (value: any) {
return isBooleanValid(value)
}
-function isUserNoModal (value: any) {
+export function isUserNoModal (value: any) {
return isBooleanValid(value)
}
-function isUserBlockedReasonValid (value: any) {
+export function isUserBlockedReasonValid (value: any) {
return value === null || (exists(value) && validator.default.isLength(value, CONSTRAINTS_FIELDS.USERS.BLOCKED_REASON))
}
-function isUserRoleValid (value: any) {
+export function isUserRoleValid (value: any) {
return exists(value) &&
validator.default.isInt('' + value) &&
[ UserRole.ADMINISTRATOR, UserRole.MODERATOR, UserRole.USER ].includes(value)
}
-
-// ---------------------------------------------------------------------------
-
-export {
- isUserVideosHistoryEnabledValid,
- isUserBlockedValid,
- isUserPasswordValid,
- isUserPasswordValidOrEmpty,
- isUserVideoLanguages,
- isUserBlockedReasonValid,
- isUserRoleValid,
- isUserVideoQuotaValid,
- isUserVideoQuotaDailyValid,
- isUserUsernameValid,
- isUserAdminFlagsValid,
- isUserEmailVerifiedValid,
- isUserNSFWPolicyValid,
- isUserP2PEnabledValid,
- isUserAutoPlayVideoValid,
- isUserAutoPlayNextVideoValid,
- isUserAutoPlayNextVideoPlaylistValid,
- isUserDisplayNameValid,
- isUserDescriptionValid,
- isUserEmailPublicValid,
- isUserNoModal
-}
diff --git a/server/core/helpers/i18n.ts b/server/core/helpers/i18n.ts
new file mode 100644
index 000000000..e760c6957
--- /dev/null
+++ b/server/core/helpers/i18n.ts
@@ -0,0 +1,76 @@
+import { AVAILABLE_LOCALES, getCompleteLocale } from '@peertube/peertube-core-utils'
+import { CONFIG } from '@server/initializers/config.js'
+import { LANGUAGE_COOKIE_NAME, LANGUAGE_HEADER, SERVER_INTERNAL_LOCALES_BASE_PATH } from '@server/initializers/constants.js'
+import { MUser } from '@server/types/models/index.js'
+import Bluebird from 'bluebird'
+import express from 'express'
+import { readJson } from 'fs-extra/esm'
+import { readdir } from 'fs/promises'
+import i18next from 'i18next'
+import ICU from 'i18next-icu'
+import { join } from 'path'
+import { logger } from './logger.js'
+
+export async function initI18n () {
+ const locales = await readdir(SERVER_INTERNAL_LOCALES_BASE_PATH)
+ const resources: Record> = {}
+
+ await Bluebird.map(locales, async locale => {
+ const localePath = join(SERVER_INTERNAL_LOCALES_BASE_PATH, locale)
+
+ const translation = await readJson(join(localePath, 'translation.json'))
+ resources[locale] = { translation }
+ }, { concurrency: 10 })
+
+ return i18next.use(ICU)
+ .init({
+ resources,
+ nsSeparator: false,
+ keySeparator: false,
+
+ // do not load a fallback
+ fallbackLng: false
+ })
+ .then(() => logger.info('i18n initialized with locales: ' + Object.keys(resources).join(', ')))
+}
+
+export function useI18n (req: express.Request, res: express.Response, next: express.NextFunction) {
+ req.t = (key: string, context: Record = {}) => {
+ // Use req special header language
+ // Or user language
+ // Or default language
+ const language = req.headers[LANGUAGE_HEADER] as string ||
+ res.locals.oauth?.token?.User?.language ||
+ req.acceptsLanguages(AVAILABLE_LOCALES) ||
+ CONFIG.INSTANCE.DEFAULT_LANGUAGE
+
+ return t(key, language, context)
+ }
+
+ next()
+}
+
+export function t (key: string, language: string, context: Record = {}) {
+ if (!language) throw new Error('Language is required for translation')
+
+ return i18next.t(key, { lng: getCompleteLocale(language), ...context })
+}
+
+export function tu (key: string, user: Pick, context: Record = {}) {
+ return t(key, user.getLanguage(), context)
+}
+
+// ---------------------------------------------------------------------------
+
+export function setClientLanguageCookie (res: express.Response, language: string) {
+ if (language === null) {
+ res.clearCookie(LANGUAGE_COOKIE_NAME)
+ return
+ }
+
+ res.cookie(LANGUAGE_COOKIE_NAME, language, {
+ secure: true,
+ sameSite: 'none',
+ maxAge: 1000 * 3600 * 24 * 90 // 3 months
+ })
+}
diff --git a/server/core/helpers/markdown.ts b/server/core/helpers/markdown.ts
index ae67b4b44..15b2c0cf3 100644
--- a/server/core/helpers/markdown.ts
+++ b/server/core/helpers/markdown.ts
@@ -1,12 +1,18 @@
import MarkdownItClass from 'markdown-it'
// FIXME: use direct import: import markdownItEmoji from 'markdown-it-emoji/lib/light.mjs' if it improves perf'
// when https://github.com/privatenumber/tsx/issues/334 is fixed
+import {
+ getDefaultSanitizeOptions,
+ getMailHtmlSanitizeOptions,
+ getTextOnlySanitizeOptions,
+ TEXT_WITH_HTML_RULES
+} from '@peertube/peertube-core-utils'
import { light as markdownItEmoji } from 'markdown-it-emoji'
import sanitizeHtml from 'sanitize-html'
-import { getDefaultSanitizeOptions, getTextOnlySanitizeOptions, TEXT_WITH_HTML_RULES } from '@peertube/peertube-core-utils'
const defaultSanitizeOptions = getDefaultSanitizeOptions()
const textOnlySanitizeOptions = getTextOnlySanitizeOptions()
+const hrefOnlySanitizeOptions = getMailHtmlSanitizeOptions()
const markdownItForSafeHtml = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
.enable(TEXT_WITH_HTML_RULES)
@@ -16,7 +22,7 @@ const markdownItForPlainText = new MarkdownItClass('default', { linkify: false,
.use(markdownItEmoji)
.use(plainTextPlugin)
-const toSafeHtml = (text: string) => {
+export const toSafeHtml = (text: string) => {
if (!text) return ''
// Restore line feed
@@ -29,7 +35,7 @@ const toSafeHtml = (text: string) => {
return sanitizeHtml(html, defaultSanitizeOptions)
}
-const mdToPlainText = (text: string) => {
+export const mdToPlainText = (text: string) => {
if (!text) return ''
markdownItForPlainText.render(text)
@@ -38,13 +44,14 @@ const mdToPlainText = (text: string) => {
return sanitizeHtml(markdownItForPlainText.plainText, textOnlySanitizeOptions)
}
-// ---------------------------------------------------------------------------
+export const toSafeMailHtml = (text: string) => {
+ if (!text) return ''
-export {
- toSafeHtml,
- mdToPlainText
+ return sanitizeHtml(text, hrefOnlySanitizeOptions)
}
+// ---------------------------------------------------------------------------
+// Private
// ---------------------------------------------------------------------------
// Thanks: https://github.com/wavesheep/markdown-it-plain-text
diff --git a/server/core/initializers/checker-before-init.ts b/server/core/initializers/checker-before-init.ts
index 5f44468e3..a1505d187 100644
--- a/server/core/initializers/checker-before-init.ts
+++ b/server/core/initializers/checker-before-init.ts
@@ -133,6 +133,7 @@ export function checkMissedConfig () {
'defaults.player.auto_play',
'instance.name',
'instance.short_description',
+ 'instance.default_language',
'instance.description',
'instance.terms',
'instance.default_client_route',
diff --git a/server/core/initializers/config.ts b/server/core/initializers/config.ts
index 003214d7c..17491d2ac 100644
--- a/server/core/initializers/config.ts
+++ b/server/core/initializers/config.ts
@@ -910,6 +910,9 @@ const CONFIG = {
return config.get('instance.hardware_information')
},
+ get DEFAULT_LANGUAGE () {
+ return config.get('instance.default_language')
+ },
get LANGUAGES () {
return config.get('instance.languages') || []
},
diff --git a/server/core/initializers/constants.ts b/server/core/initializers/constants.ts
index ca4a69ba0..6b62dc98e 100644
--- a/server/core/initializers/constants.ts
+++ b/server/core/initializers/constants.ts
@@ -48,7 +48,7 @@ import { CONFIG, registerConfigChangedHandler } from './config.js'
// ---------------------------------------------------------------------------
-export const LAST_MIGRATION_VERSION = 905
+export const LAST_MIGRATION_VERSION = 910
// ---------------------------------------------------------------------------
@@ -1119,6 +1119,9 @@ export const REDUNDANCY = {
}
export const ACCEPT_HEADERS = [ 'html', 'application/json' ].concat(ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS)
+export const LANGUAGE_COOKIE_NAME = 'clientLanguage'
+export const LANGUAGE_HEADER = 'x-peertube-language'
+
export const OTP = {
HEADER_NAME: 'x-peertube-otp',
HEADER_REQUIRED_VALUE: 'required; app'
@@ -1129,6 +1132,8 @@ export const ASSETS_PATH = {
DEFAULT_LIVE_BACKGROUND: join(root(), 'dist', 'core', 'assets', 'default-live-background.jpg')
}
+export const SERVER_INTERNAL_LOCALES_BASE_PATH = join(root(), 'dist', 'locales')
+
// ---------------------------------------------------------------------------
export const CUSTOM_HTML_TAG_COMMENTS = {
diff --git a/server/core/initializers/migrations/0910-user-language.ts b/server/core/initializers/migrations/0910-user-language.ts
new file mode 100644
index 000000000..3d80a6807
--- /dev/null
+++ b/server/core/initializers/migrations/0910-user-language.ts
@@ -0,0 +1,26 @@
+import * as Sequelize from 'sequelize'
+
+async function up (utils: {
+ transaction: Sequelize.Transaction
+ queryInterface: Sequelize.QueryInterface
+ sequelize: Sequelize.Sequelize
+}): Promise {
+ const { transaction } = utils
+
+ {
+ await utils.queryInterface.addColumn('user', 'language', {
+ type: Sequelize.STRING,
+ defaultValue: null,
+ allowNull: true
+ }, { transaction })
+ }
+}
+
+function down (options) {
+ throw new Error('Not implemented.')
+}
+
+export {
+ down,
+ up
+}
diff --git a/server/core/lib/client-urls.ts b/server/core/lib/client-urls.ts
new file mode 100644
index 000000000..100dfee35
--- /dev/null
+++ b/server/core/lib/client-urls.ts
@@ -0,0 +1,36 @@
+import { PluginType_Type } from '@peertube/peertube-models'
+import { WEBSERVER } from '@server/initializers/constants.js'
+import { MAbuseId, MUserId } from '@server/types/models/index.js'
+
+export const instanceFollowingUrl = `${WEBSERVER.URL}/admin/settings/follows/following-list`
+export const instanceFollowersUrl = `${WEBSERVER.URL}/admin/follows/followers-list`
+export const videoAutoBlacklistUrl = `${WEBSERVER.URL}/admin/moderation/video-blocks/list`
+export const myAccountImportExportUrl = `${WEBSERVER.URL}/my-account/import-export`
+export const loginUrl = `${WEBSERVER.URL}/login`
+export const adminRegistrationsListUrl = `${WEBSERVER.URL}/admin/moderation/registrations/list`
+export const adminUsersListUrl = `${WEBSERVER.URL}/admin/overview/users/list`
+export const myVideoImportsUrl = `${WEBSERVER.URL}/my-library/video-imports`
+
+export function getAdminAbuseUrl (abuse: MAbuseId) {
+ const suffix = abuse
+ ? '?search=%23' + abuse.id
+ : ''
+
+ return WEBSERVER.URL + 'admin/moderation/abuses/list' + suffix
+}
+
+export function getUserAbuseUrl (abuse: MAbuseId) {
+ const suffix = abuse
+ ? '?search=%23' + abuse.id
+ : ''
+
+ return WEBSERVER.URL + '/my-account/abuses' + suffix
+}
+
+export function getResetPasswordUrl (user: MUserId, verificationString: string) {
+ return WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
+}
+
+export function getPluginUrl (pluginType: PluginType_Type) {
+ return WEBSERVER.URL + '/admin/settings/plugins/list-installed?pluginType=' + pluginType
+}
diff --git a/server/core/lib/emailer.ts b/server/core/lib/emailer.ts
index 11411119d..dee37a274 100644
--- a/server/core/lib/emailer.ts
+++ b/server/core/lib/emailer.ts
@@ -1,24 +1,35 @@
import { arrayify } from '@peertube/peertube-core-utils'
-import { EmailPayload, SendEmailDefaultOptions, UserExportState, UserRegistrationState } from '@peertube/peertube-models'
-import { isTestOrDevInstance, root } from '@peertube/peertube-node-utils'
+import { EmailPayload, SendEmailDefaultOptions, To, UserExportState, UserRegistrationState } from '@peertube/peertube-models'
+import { getFilenameWithoutExt, isTestOrDevInstance, root } from '@peertube/peertube-node-utils'
+import { t } from '@server/helpers/i18n.js'
+import { toSafeMailHtml } from '@server/helpers/markdown.js'
+import { getServerActor } from '@server/models/application/application.js'
import { UserModel } from '@server/models/user/user.js'
import { readFileSync } from 'fs'
+import { readdir, readFile } from 'fs/promises'
+import handlebars, { HelperOptions } from 'handlebars'
import merge from 'lodash-es/merge.js'
-import { Transporter, createTransport } from 'nodemailer'
+import { createTransport, Transporter } from 'nodemailer'
import { join } from 'path'
-import pug from 'pug'
import { bunyanLogger, logger } from '../helpers/logger.js'
import { CONFIG, isEmailEnabled } from '../initializers/config.js'
import { WEBSERVER } from '../initializers/constants.js'
-import { MRegistration, MUser, MUserExport, MUserImport } from '../types/models/index.js'
+import { MRegistration, MUserExport, MUserImport } from '../types/models/index.js'
+import { loginUrl, myAccountImportExportUrl } from './client-urls.js'
import { JobQueue } from './job-queue/index.js'
import { Hooks } from './plugins/hooks.js'
+import { ServerConfigManager } from './server-config-manager.js'
export class Emailer {
private static instance: Emailer
+
private initialized = false
+ private registeringHandlebars: Promise
+
private transporter: Transporter
+ private readonly compiledTemplates = new Map()
+
private constructor () {
}
@@ -56,11 +67,18 @@ export class Emailer {
// ---------------------------------------------------------------------------
- addPasswordResetEmailJob (username: string, to: string, resetPasswordUrl: string) {
+ addPasswordResetEmailJob (options: {
+ username: string
+ to: string
+ language: string
+ resetPasswordUrl: string
+ }) {
+ const { username, to, resetPasswordUrl, language } = options
+
const emailPayload: EmailPayload = {
template: 'password-reset',
- to: [ to ],
- subject: 'Reset your account password',
+ to: { email: to, language },
+ subject: t('Reset your account password', language),
locals: {
username,
resetPasswordUrl,
@@ -72,11 +90,18 @@ export class Emailer {
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- addPasswordCreateEmailJob (username: string, to: string, createPasswordUrl: string) {
+ addPasswordCreateEmailJob (options: {
+ username: string
+ to: string
+ language: string
+ createPasswordUrl: string
+ }) {
+ const { username, to, createPasswordUrl, language } = options
+
const emailPayload: EmailPayload = {
template: 'password-create',
- to: [ to ],
- subject: 'Create your account password',
+ to: { email: to, language },
+ subject: t('Create your account password', language),
locals: {
username,
createPasswordUrl,
@@ -91,14 +116,15 @@ export class Emailer {
addUserVerifyChangeEmailJob (options: {
username: string
to: string
+ language: string
verifyEmailUrl: string
}) {
- const { username, to, verifyEmailUrl } = options
+ const { username, to, verifyEmailUrl, language } = options
const emailPayload: EmailPayload = {
template: 'verify-user-change-email',
- to: [ to ],
- subject: `Verify your email on ${CONFIG.INSTANCE.NAME}`,
+ to: { email: to, language },
+ subject: t('Verify your email on {instanceName}', language, { instanceName: CONFIG.INSTANCE.NAME }),
locals: {
username,
verifyEmailUrl,
@@ -114,14 +140,16 @@ export class Emailer {
username: string
isRegistrationRequest: boolean
to: string
+ language: string
verifyEmailUrl: string
}) {
- const { username, isRegistrationRequest, to, verifyEmailUrl } = options
+ const { username, isRegistrationRequest, to, verifyEmailUrl, language } = options
const emailPayload: EmailPayload = {
template: 'verify-registration-email',
- to: [ to ],
- subject: `Verify your email on ${CONFIG.INSTANCE.NAME}`,
+ to: { email: to, language },
+
+ subject: t('Verify your email on {instanceName}', language, { instanceName: CONFIG.INSTANCE.NAME }),
locals: {
username,
verifyEmailUrl,
@@ -134,26 +162,53 @@ export class Emailer {
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- addUserBlockJob (user: MUser, blocked: boolean, reason?: string) {
- const reasonString = reason ? ` for the following reason: ${reason}` : ''
- const blockedWord = blocked ? 'blocked' : 'unblocked'
+ addUserBlockJob (options: {
+ username: string
+ email: string
+ language: string
+ blocked: boolean
+ reason?: string
+ }) {
+ const { username, language, email, blocked, reason } = options
- const to = user.email
- const emailPayload: EmailPayload = {
- to: [ to ],
- subject: 'Account ' + blockedWord,
- text: `Your account ${user.username} on ${CONFIG.INSTANCE.NAME} has been ${blockedWord}${reasonString}.`
- }
+ const emailPayload = blocked
+ ? {
+ template: 'my-user-block-new',
+ to: { email, language },
+ subject: t('Your account has been blocked', language),
+ locals: {
+ username,
+ instanceName: CONFIG.INSTANCE.NAME,
+ reason
+ }
+ }
+ : {
+ template: 'my-user-unblocked',
+ to: { email, language },
+ subject: t('Your account has been unblocked', language),
+ locals: {
+ username,
+ instanceName: CONFIG.INSTANCE.NAME
+ }
+ }
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- addContactFormJob (fromEmail: string, fromName: string, subject: string, body: string) {
+ addContactFormJob (options: {
+ fromEmail: string
+
+ fromName: string
+ subject: string
+ body: string
+ }) {
+ const { fromEmail, fromName, subject, body } = options
+
const emailPayload: EmailPayload = {
template: 'contact-form',
- to: [ CONFIG.ADMIN.EMAIL ],
+ to: { email: CONFIG.ADMIN.EMAIL, language: CONFIG.INSTANCE.DEFAULT_LANGUAGE },
replyTo: `"${fromName}" <${fromEmail}>`,
- subject: `(contact form) ${subject}`,
+ subject: t('Contact form - {subject}', CONFIG.INSTANCE.DEFAULT_LANGUAGE, { subject }),
locals: {
fromName,
fromEmail,
@@ -167,26 +222,34 @@ export class Emailer {
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- addUserRegistrationRequestProcessedJob (registration: MRegistration) {
+ addUserRegistrationRequestProcessedJob (
+ registration: Pick
+ ) {
+ const language = CONFIG.INSTANCE.DEFAULT_LANGUAGE
+
let template: string
let subject: string
+ let action: { text: string, href: string }
+
if (registration.state === UserRegistrationState.ACCEPTED) {
template = 'user-registration-request-accepted'
- subject = `Your registration request for ${registration.username} has been accepted`
+ subject = t('Your registration request for {username} has been accepted', language, { username: registration.username })
+
+ action = { text: t('Login to your account', language), href: loginUrl }
} else {
template = 'user-registration-request-rejected'
- subject = `Your registration request for ${registration.username} has been rejected`
+ subject = t('Your registration request for {username} has been rejected', language, { username: registration.username })
}
const to = registration.email
const emailPayload: EmailPayload = {
- to: [ to ],
+ to: { email: to, language },
template,
subject,
locals: {
username: registration.username,
moderationResponse: registration.moderationResponse,
- loginLink: WEBSERVER.URL + '/login',
+ action,
hideNotificationPreferencesLink: true
}
@@ -197,26 +260,26 @@ export class Emailer {
// ---------------------------------------------------------------------------
- async addUserExportCompletedOrErroredJob (userExport: MUserExport) {
+ async addUserExportCompletedOrErroredJob (userExport: Pick, toOverride?: To) {
let template: string
let subject: string
+ const to = toOverride ?? await UserModel.loadForEmail(userExport.userId)
+
if (userExport.state === UserExportState.COMPLETED) {
template = 'user-export-completed'
- subject = `Your export archive has been created`
+ subject = t('Your export archive has been created', to.language)
} else {
template = 'user-export-errored'
- subject = `Failed to create your export archive`
+ subject = t('Failed to create your export archive', to.language)
}
- const user = await UserModel.loadById(userExport.userId)
-
const emailPayload: EmailPayload = {
- to: [ user.email ],
+ to,
template,
subject,
locals: {
- exportsUrl: WEBSERVER.URL + '/my-account/import-export',
+ exportsUrl: myAccountImportExportUrl,
errorMessage: userExport.error,
hideNotificationPreferencesLink: true
@@ -226,13 +289,14 @@ export class Emailer {
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- async addUserImportErroredJob (userImport: MUserImport) {
- const user = await UserModel.loadById(userImport.userId)
+ async addUserImportErroredJob (userImport: Pick, toOverride?: To) {
+ const to = toOverride ?? await UserModel.loadForEmail(userImport.userId)
const emailPayload: EmailPayload = {
- to: [ user.email ],
+ to,
+
template: 'user-import-errored',
- subject: 'Failed to import your archive',
+ subject: t('Failed to import your archive', to.language),
locals: {
errorMessage: userImport.error,
@@ -243,13 +307,14 @@ export class Emailer {
return JobQueue.Instance.createJobAsync({ type: 'email', payload: emailPayload })
}
- async addUserImportSuccessJob (userImport: MUserImport) {
- const user = await UserModel.loadById(userImport.userId)
+ async addUserImportSuccessJob (userImport: Pick, toOverride?: To) {
+ const to = toOverride ?? await UserModel.loadForEmail(userImport.userId)
const emailPayload: EmailPayload = {
- to: [ user.email ],
+ to,
+
template: 'user-import-completed',
- subject: 'Your archive import has finished',
+ subject: t('Your archive import has finished', to.language),
locals: {
resultStats: userImport.resultSummary.stats,
@@ -286,12 +351,20 @@ export class Emailer {
render: async (view: string, locals: Record) => {
if (view.split('/').pop() !== 'html') return undefined
+ await this.initHandlebarsIfNeeded()
+
const templatePath = await Hooks.wrapObject(
- join(root(), 'dist', 'core', 'assets', 'email-templates', view + '.pug'),
+ join(root(), 'dist', 'core', 'assets', 'email-templates', view + '.hbs'),
'filter:email.template-path.result',
{ view }
)
- const compiledTemplate = pug.compileFile(templatePath)
+
+ let compiledTemplate = this.compiledTemplates.get(templatePath)
+
+ if (!compiledTemplate) {
+ compiledTemplate = handlebars.compile(await readFile(templatePath, 'utf-8'))
+ this.compiledTemplates.set(templatePath, compiledTemplate)
+ }
return compiledTemplate(locals)
},
@@ -307,15 +380,13 @@ export class Emailer {
{ template: 'template' in options ? options.template : undefined }
)
- const toEmails = arrayify(options.to)
-
const errors: Error[] = []
- for (const to of toEmails) {
+ for (const to of arrayify(options.to)) {
const baseOptions: SendEmailDefaultOptions = {
template: 'common',
message: {
- to,
+ to: to.email,
from: options.from,
subject,
replyTo: options.replyTo
@@ -328,7 +399,9 @@ export class Emailer {
signature: this.buildSignature(),
fg: CONFIG.THEME.CUSTOMIZATION.FOREGROUND_COLOR || '#000',
bg: CONFIG.THEME.CUSTOMIZATION.BACKGROUND_COLOR || '#fff',
- primary: CONFIG.THEME.CUSTOMIZATION.PRIMARY_COLOR || '#FF8F37'
+ primary: CONFIG.THEME.CUSTOMIZATION.PRIMARY_COLOR || '#FF8F37',
+ language: to.language,
+ logoUrl: ServerConfigManager.Instance.getLogoUrl(await getServerActor(), 192)
}
}
@@ -416,6 +489,29 @@ export class Emailer {
return signature.replace(/{{instanceName}}/g, CONFIG.INSTANCE.NAME)
}
+ private initHandlebarsIfNeeded () {
+ if (this.registeringHandlebars) return this.registeringHandlebars
+
+ this.registeringHandlebars = this._initHandlebarsIfNeeded()
+
+ return this.registeringHandlebars
+ }
+
+ private async _initHandlebarsIfNeeded () {
+ const partialsPath = join(root(), 'server', 'core', 'assets', 'email-templates', 'partials')
+ const partialFiles = await readdir(partialsPath)
+
+ for (const partialFile of partialFiles) {
+ handlebars.registerPartial(getFilenameWithoutExt(partialFile), await readFile(join(partialsPath, partialFile), 'utf-8'))
+ }
+
+ handlebars.registerHelper('t', function (key: string, options: HelperOptions) {
+ const result = t(key, this.language, options.hash)
+
+ return toSafeMailHtml(result)
+ })
+ }
+
static get Instance () {
return this.instance || (this.instance = new this())
}
diff --git a/server/core/lib/html/shared/page-html.ts b/server/core/lib/html/shared/page-html.ts
index cc8b95203..df3b9c11e 100644
--- a/server/core/lib/html/shared/page-html.ts
+++ b/server/core/lib/html/shared/page-html.ts
@@ -1,13 +1,14 @@
import {
+ AVAILABLE_LOCALES,
buildFileLocale,
escapeHTML,
getDefaultLocale,
getDefaultRSSFeeds,
- is18nLocale,
- POSSIBLE_LOCALES
+ is18nLocale
} from '@peertube/peertube-core-utils'
import { HTMLServerConfig } from '@peertube/peertube-models'
import { isTestOrDevInstance, root, sha256 } from '@peertube/peertube-node-utils'
+import { setClientLanguageCookie } from '@server/helpers/i18n.js'
import { CONFIG } from '@server/initializers/config.js'
import { getServerActor } from '@server/models/application/application.js'
import express from 'express'
@@ -125,15 +126,11 @@ export class PageHtml {
lang = paramLang
// Save locale in cookies
- res.cookie('clientLanguage', lang, {
- secure: true,
- sameSite: 'none',
- maxAge: 1000 * 3600 * 24 * 90 // 3 months
- })
+ setClientLanguageCookie(res, lang)
} else if (req.cookies.clientLanguage && is18nLocale(req.cookies.clientLanguage)) {
lang = req.cookies.clientLanguage
} else {
- lang = req.acceptsLanguages(POSSIBLE_LOCALES) || getDefaultLocale()
+ lang = req.acceptsLanguages(AVAILABLE_LOCALES) || getDefaultLocale()
}
logger.debug(
diff --git a/server/core/lib/html/shared/tags-html.ts b/server/core/lib/html/shared/tags-html.ts
index 622525033..53c239665 100644
--- a/server/core/lib/html/shared/tags-html.ts
+++ b/server/core/lib/html/shared/tags-html.ts
@@ -1,4 +1,4 @@
-import { escapeAttribute, escapeHTML, findAppropriateImage } from '@peertube/peertube-core-utils'
+import { escapeAttribute, escapeHTML } from '@peertube/peertube-core-utils'
import { mdToPlainText } from '@server/helpers/markdown.js'
import { ServerConfigManager } from '@server/lib/server-config-manager.js'
import { getServerActor } from '@server/models/application/application.js'
@@ -148,10 +148,7 @@ export class TagsHtml {
tagsStr += ` `
// Apple Touch Icon
- const appleTouchIcon = findAppropriateImage(serverActor.Avatars, 192)
- const iconHref = appleTouchIcon
- ? WEBSERVER.URL + appleTouchIcon.getStaticPath()
- : '/client/assets/images/icons/icon-192x192.png'
+ const iconHref = ServerConfigManager.Instance.getLogoUrl(serverActor, 192)
tagsStr += ` `
diff --git a/server/core/lib/notifier/notifier.ts b/server/core/lib/notifier/notifier.ts
index 59ab31331..a2cf1f396 100644
--- a/server/core/lib/notifier/notifier.ts
+++ b/server/core/lib/notifier/notifier.ts
@@ -1,5 +1,5 @@
import { UserNotificationSettingValue, UserNotificationSettingValueType } from '@peertube/peertube-models'
-import { MRegistration, MUser, MUserDefault } from '@server/types/models/user/index.js'
+import { MRegistration, MUser, MUserDefault, MUserWithNotificationSetting } from '@server/types/models/user/index.js'
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist.js'
import { logger, loggerTagsFactory } from '../../helpers/logger.js'
import { CONFIG } from '../../initializers/config.js'
@@ -49,7 +49,6 @@ import {
const lTags = loggerTagsFactory('notifier')
class Notifier {
-
private readonly notificationModels = {
newVideoOrLive: [ NewVideoOrLiveForSubscribers ],
publicationAfterTranscoding: [ OwnedPublicationAfterTranscoding ],
@@ -169,7 +168,7 @@ class Notifier {
logger.debug('Notify on video unblacklist', { video: video.url, ...lTags() })
this.sendNotifications(models, video)
- .catch(err => logger.error('Cannot notify video owner of unblacklist of %s.', video.url, { err }))
+ .catch(err => logger.error('Cannot notify video owner of unblacklist of %s.', video.url, { err }))
}
notifyOnFinishedVideoImport (payload: ImportFinishedForOwnerPayload): void {
@@ -178,9 +177,9 @@ class Notifier {
logger.debug('Notify on finished video import', { import: payload.videoImport.getTargetIdentifier(), ...lTags() })
this.sendNotifications(models, payload)
- .catch(err => {
- logger.error('Cannot notify owner that its video import %s is finished.', payload.videoImport.getTargetIdentifier(), { err })
- })
+ .catch(err => {
+ logger.error('Cannot notify owner that its video import %s is finished.', payload.videoImport.getTargetIdentifier(), { err })
+ })
}
notifyOnNewDirectRegistration (user: MUserDefault): void {
@@ -288,7 +287,7 @@ class Notifier {
.catch(err => logger.error('Cannot notify on generated video transcription %s of video %s.', caption.language, video.url, { err }))
}
- private async notify (object: AbstractNotification) {
+ private async notify (object: AbstractNotification) {
await object.prepare()
const users = object.getTargetUsers()
@@ -298,7 +297,7 @@ class Notifier {
object.log()
- const toEmails: string[] = []
+ const toUsers: MUserWithNotificationSetting[] = []
for (const user of users) {
const setting = object.getSetting(user)
@@ -314,13 +313,13 @@ class Notifier {
}
if (emailNotificationEnabled) {
- toEmails.push(user.email)
+ toUsers.push(user)
}
Hooks.runAction('action:notifier.notification.created', { webNotificationEnabled, emailNotificationEnabled, user, notification })
}
- for (const to of toEmails) {
+ for (const to of toUsers) {
const payload = await object.createEmail(to)
JobQueue.Instance.createJobAsync({ type: 'email', payload })
}
@@ -336,7 +335,7 @@ class Notifier {
return (value & UserNotificationSettingValue.WEB) === UserNotificationSettingValue.WEB
}
- private async sendNotifications (models: (new (payload: T) => AbstractNotification)[], payload: T) {
+ private async sendNotifications (models: (new(payload: T) => AbstractNotification)[], payload: T) {
for (const model of models) {
// eslint-disable-next-line new-cap
await this.notify(new model(payload))
diff --git a/server/core/lib/notifier/shared/abuse/abstract-new-abuse-message.ts b/server/core/lib/notifier/shared/abuse/abstract-new-abuse-message.ts
index f9a940299..efbdb8194 100644
--- a/server/core/lib/notifier/shared/abuse/abstract-new-abuse-message.ts
+++ b/server/core/lib/notifier/shared/abuse/abstract-new-abuse-message.ts
@@ -1,5 +1,6 @@
-import { UserNotificationType } from '@peertube/peertube-models'
-import { WEBSERVER } from '@server/initializers/constants.js'
+import { To, UserNotificationType } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
+import { getAdminAbuseUrl, getUserAbuseUrl } from '@server/lib/client-urls.js'
import { AccountModel } from '@server/models/account/account.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
import {
@@ -16,7 +17,7 @@ type NewAbuseMessagePayload = {
message: MAbuseMessage
}
-export abstract class AbstractNewAbuseMessage extends AbstractNotification {
+export abstract class AbstractNewAbuseMessage extends AbstractNotification {
protected messageAccount: MAccountDefault
async loadMessageAccount () {
@@ -38,14 +39,14 @@ export abstract class AbstractNewAbuseMessage extends AbstractNotification {
-
+export class AbuseStateChangeForReporter extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -43,15 +43,18 @@ export class AbuseStateChangeForReporter extends AbstractNotification , abuseInstance: MAbuseFull, reporter: string }
-export class NewAbuseForModerators extends AbstractNotification {
+export class NewAbuseForModerators extends AbstractNotification {
private moderators: MUserDefault[]
async prepare () {
@@ -39,7 +41,9 @@ export class NewAbuseForModerators extends AbstractNotification {
+export class NewAutoBlacklistForModerators extends AbstractNotification {
private moderators: MUserDefault[]
async prepare () {
@@ -42,21 +44,21 @@ export class NewAutoBlacklistForModerators extends AbstractNotification {
+export class NewBlacklistForOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -44,19 +45,24 @@ export class NewBlacklistForOwner extends AbstractNotification {
+export class UnblacklistForOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -39,16 +40,23 @@ export class UnblacklistForOwner extends AbstractNotification
return notification
}
- createEmail (to: string) {
+ createEmail (user: MUserWithNotificationSetting) {
+ const to = { email: user.email, language: user.getLanguage() }
+
const video = this.payload
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
return {
+ template: 'video-owner-unblacklist',
to,
- subject: `Video ${video.name} unblacklisted`,
- text: `Your video "${video.name}" (${videoUrl}) on ${CONFIG.INSTANCE.NAME} has been unblacklisted.`,
+ subject: tu('Your video has been unblocked', user),
locals: {
- title: 'Your video was unblacklisted'
+ instanceName: CONFIG.INSTANCE.NAME,
+ videoName: video.name,
+ action: {
+ text: tu('View video', user),
+ url: videoUrl
+ }
}
}
}
diff --git a/server/core/lib/notifier/shared/caption/video-transcription-generated-for-owner.ts b/server/core/lib/notifier/shared/caption/video-transcription-generated-for-owner.ts
index a77740736..2d0d4dd01 100644
--- a/server/core/lib/notifier/shared/caption/video-transcription-generated-for-owner.ts
+++ b/server/core/lib/notifier/shared/caption/video-transcription-generated-for-owner.ts
@@ -1,4 +1,5 @@
import { UserNotificationType } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
import { logger } from '@server/helpers/logger.js'
import { VIDEO_LANGUAGES, WEBSERVER } from '@server/initializers/constants.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
@@ -6,7 +7,7 @@ import { UserModel } from '@server/models/user/user.js'
import { MUserDefault, MUserWithNotificationSetting, MVideoCaptionVideo, UserNotificationModelForApi } from '@server/types/models/index.js'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class VideoTranscriptionGeneratedForOwner extends AbstractNotification {
+export class VideoTranscriptionGeneratedForOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -16,7 +17,9 @@ export class VideoTranscriptionGeneratedForOwner extends AbstractNotification {
+export class CommentMention extends AbstractNotification {
private users: MUserDefault[]
private serverAccountId: number
- private accountMutedHash: { [ id: number ]: boolean }
- private instanceMutedHash: { [ id: number ]: boolean }
+ private accountMutedHash: { [id: number]: boolean }
+ private instanceMutedHash: { [id: number]: boolean }
isDisabled () {
return this.payload.heldForReview === true
@@ -31,7 +32,9 @@ export class CommentMention extends AbstractNotification {
+export class NewCommentForVideoOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -49,7 +50,9 @@ export class NewCommentForVideoOwner extends AbstractNotification {
-
+export abstract class AbstractNotification {
constructor (protected readonly payload: T) {
-
}
abstract prepare (): Promise
@@ -14,10 +12,9 @@ export abstract class AbstractNotification
abstract getTargetUsers (): U[]
abstract createNotification (user: U): UserNotificationModelForApi
- abstract createEmail (to: string): EmailPayload | Promise
+ abstract createEmail (to: U): EmailPayload | Promise
isDisabled (): boolean | Promise {
return false
}
-
}
diff --git a/server/core/lib/notifier/shared/follow/auto-follow-for-instance.ts b/server/core/lib/notifier/shared/follow/auto-follow-for-instance.ts
index 027bf8eef..f6ea20f8e 100644
--- a/server/core/lib/notifier/shared/follow/auto-follow-for-instance.ts
+++ b/server/core/lib/notifier/shared/follow/auto-follow-for-instance.ts
@@ -1,11 +1,13 @@
-import { logger } from '@server/helpers/logger.js'
-import { UserModel } from '@server/models/user/user.js'
-import { UserNotificationModel } from '@server/models/user/user-notification.js'
-import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
import { UserNotificationType, UserRight } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
+import { logger } from '@server/helpers/logger.js'
+import { instanceFollowingUrl } from '@server/lib/client-urls.js'
+import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
+import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class AutoFollowForInstance extends AbstractNotification {
+export class AutoFollowForInstance extends AbstractNotification {
private admins: MUserDefault[]
async prepare () {
@@ -35,13 +37,21 @@ export class AutoFollowForInstance extends AbstractNotification ${instanceUrl}.`
+ subject: t('Auto platform follow', to.language),
+ text: `Your platform automatically followed ${subscription.getIdentifier()}`,
+ locals: {
+ action: {
+ text: t('View subscription', to.language),
+ url: instanceFollowingUrl
+ }
+ }
}
}
diff --git a/server/core/lib/notifier/shared/follow/follow-for-instance.ts b/server/core/lib/notifier/shared/follow/follow-for-instance.ts
index 76fa0332a..4e60b4974 100644
--- a/server/core/lib/notifier/shared/follow/follow-for-instance.ts
+++ b/server/core/lib/notifier/shared/follow/follow-for-instance.ts
@@ -1,13 +1,15 @@
+import { UserNotificationType, UserRight } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
import { logger } from '@server/helpers/logger.js'
+import { CONFIG } from '@server/initializers/config.js'
import { WEBSERVER } from '@server/initializers/constants.js'
import { isBlockedByServerOrAccount } from '@server/lib/blocklist.js'
-import { UserModel } from '@server/models/user/user.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
-import { UserNotificationType, UserRight } from '@peertube/peertube-models'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class FollowForInstance extends AbstractNotification {
+export class FollowForInstance extends AbstractNotification {
private admins: MUserDefault[]
async prepare () {
@@ -43,19 +45,23 @@ export class FollowForInstance extends AbstractNotification {
return notification
}
- createEmail (to: string) {
- const awaitingApproval = this.actorFollow.state === 'pending'
- ? ' awaiting manual approval.'
- : ''
+ createEmail (user: MUserWithNotificationSetting) {
+ const to = { email: user.email, language: user.getLanguage() }
+ const language = user.getLanguage()
+
+ const context = { instanceName: CONFIG.INSTANCE.NAME, handle: this.actorFollow.ActorFollower.getIdentifier() }
+
+ const text = this.actorFollow.state === 'pending'
+ ? t('{instanceName} has a new follower, {handle}, awaiting manual approval.', language, context)
+ : t('{instanceName} has a new follower: {handle}.', language, context)
return {
to,
- subject: 'New instance follower',
- text: `Your instance has a new follower: ${this.actorFollow.ActorFollower.url}${awaitingApproval}.`,
+ subject: t('New follower for {instanceName}', language, { instanceName: CONFIG.INSTANCE.NAME }),
+ text,
locals: {
- title: 'New instance follower',
action: {
- text: 'Review followers',
+ text: t('Review followers', language),
url: WEBSERVER.URL + '/admin/follows/followers-list'
}
}
diff --git a/server/core/lib/notifier/shared/follow/follow-for-user.ts b/server/core/lib/notifier/shared/follow/follow-for-user.ts
index bf915dfeb..3e79a136c 100644
--- a/server/core/lib/notifier/shared/follow/follow-for-user.ts
+++ b/server/core/lib/notifier/shared/follow/follow-for-user.ts
@@ -1,12 +1,13 @@
+import { UserNotificationType } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
import { logger } from '@server/helpers/logger.js'
import { isBlockedByServerOrAccount } from '@server/lib/blocklist.js'
-import { UserModel } from '@server/models/user/user.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
import { MActorFollowFull, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
-import { UserNotificationType } from '@peertube/peertube-models'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class FollowForUser extends AbstractNotification {
+export class FollowForUser extends AbstractNotification {
private followType: 'account' | 'channel'
private user: MUserDefault
@@ -56,22 +57,30 @@ export class FollowForUser extends AbstractNotification {
return notification
}
- createEmail (to: string) {
+ createEmail (user: MUserWithNotificationSetting) {
+ const to = { email: user.email, language: user.getLanguage() }
+
const following = this.actorFollow.ActorFollowing
const follower = this.actorFollow.ActorFollower
- const followingName = (following.VideoChannel || following.Account).getDisplayName()
+ const followingAccountOrChannel = Object.assign(following.VideoChannel || following.Account, { Actor: following })
+ const followerAccountOrChannel = Object.assign(follower.VideoChannel || follower.Account, { Actor: follower })
+ const followingName = followingAccountOrChannel.getDisplayName()
return {
template: 'follower-on-channel',
to,
- subject: `New follower on your channel ${followingName}`,
+
+ subject: this.followType === 'account'
+ ? t('New follower on your account {followingName}', to.language, { followingName })
+ : t('New follower on your channel {followingName}', to.language, { followingName }),
+
locals: {
followerName: follower.Account.getDisplayName(),
- followerUrl: follower.url,
+ followerUrl: followerAccountOrChannel.getClientUrl(),
+ followingUrl: followingAccountOrChannel.getClientUrl(),
followingName,
- followingUrl: following.url,
- followType: this.followType
+ accountFollowType: this.followType === 'account'
}
}
}
diff --git a/server/core/lib/notifier/shared/instance/direct-registration-for-moderators.ts b/server/core/lib/notifier/shared/instance/direct-registration-for-moderators.ts
index 42078ba24..f7bbf9443 100644
--- a/server/core/lib/notifier/shared/instance/direct-registration-for-moderators.ts
+++ b/server/core/lib/notifier/shared/instance/direct-registration-for-moderators.ts
@@ -1,12 +1,14 @@
+import { UserNotificationType, UserRight } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
import { logger } from '@server/helpers/logger.js'
import { CONFIG } from '@server/initializers/config.js'
-import { UserModel } from '@server/models/user/user.js'
+import { adminUsersListUrl } from '@server/lib/client-urls.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
import { MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
-import { UserNotificationType, UserRight } from '@peertube/peertube-models'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class DirectRegistrationForModerators extends AbstractNotification {
+export class DirectRegistrationForModerators extends AbstractNotification {
private moderators: MUserDefault[]
async prepare () {
@@ -36,13 +38,22 @@ export class DirectRegistrationForModerators extends AbstractNotification {
+export class NewPeerTubeVersionForAdmins extends AbstractNotification {
private admins: MUserDefault[]
async prepare () {
@@ -41,11 +42,13 @@ export class NewPeerTubeVersionForAdmins extends AbstractNotification {
+export class NewPluginVersionForAdmins extends AbstractNotification {
private admins: MUserDefault[]
async prepare () {
@@ -37,16 +38,25 @@ export class NewPluginVersionForAdmins extends AbstractNotification {
return notification
}
- createEmail (to: string) {
- const pluginUrl = WEBSERVER.URL + '/admin/settings/plugins/list-installed?pluginType=' + this.plugin.type
+ createEmail (user: MUserWithNotificationSetting) {
+ const to = { email: user.email, language: user.getLanguage() }
+ const language = user.getLanguage()
+
+ const pluginUrl = getPluginUrl(this.plugin.type)
+ const context = { pluginName: this.plugin.name, latestVersion: this.plugin.latestVersion }
return {
to,
template: 'plugin-version-new',
- subject: `A new plugin/theme version is available: ${this.plugin.name}@${this.plugin.latestVersion}`,
+
+ subject: this.plugin.type === PluginType.PLUGIN
+ ? t('A new version of the plugin {pluginName} is available: {latestVersion}', language, context)
+ : t('A new version of the theme {pluginName} is available: {latestVersion}', language, context),
+
locals: {
pluginName: this.plugin.name,
latestVersion: this.plugin.latestVersion,
+ isPlugin: this.plugin.type === PluginType.PLUGIN,
pluginUrl
}
}
diff --git a/server/core/lib/notifier/shared/instance/registration-request-for-moderators.ts b/server/core/lib/notifier/shared/instance/registration-request-for-moderators.ts
index 29dda28be..e6281f7ea 100644
--- a/server/core/lib/notifier/shared/instance/registration-request-for-moderators.ts
+++ b/server/core/lib/notifier/shared/instance/registration-request-for-moderators.ts
@@ -1,11 +1,14 @@
-import { logger } from '@server/helpers/logger.js'
-import { UserModel } from '@server/models/user/user.js'
-import { UserNotificationModel } from '@server/models/user/user-notification.js'
-import { MRegistration, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
import { UserNotificationType, UserRight } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
+import { logger } from '@server/helpers/logger.js'
+import { CONFIG } from '@server/initializers/config.js'
+import { adminRegistrationsListUrl } from '@server/lib/client-urls.js'
+import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
+import { MRegistration, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models/index.js'
import { AbstractNotification } from '../common/abstract-notification.js'
-export class RegistrationRequestForModerators extends AbstractNotification {
+export class RegistrationRequestForModerators extends AbstractNotification {
private moderators: MUserDefault[]
async prepare () {
@@ -35,13 +38,21 @@ export class RegistrationRequestForModerators extends AbstractNotification {
+export abstract class AbstractOwnedVideoPublication extends AbstractNotification {
protected user: MUserDefault
async prepare () {
@@ -38,17 +39,20 @@ export abstract class AbstractOwnedVideoPublication extends AbstractNotification
return notification
}
- createEmail (to: string) {
+ createEmail (user: MUserWithNotificationSetting) {
+ const to = { email: user.email, language: user.getLanguage() }
+ const language = user.getLanguage()
+
const videoUrl = WEBSERVER.URL + this.payload.getWatchStaticPath()
return {
to,
- subject: `Your video ${this.payload.name} has been published`,
- text: `Your video "${this.payload.name}" has been published.`,
+ subject: t('Your video has been published', language),
+ text: t('Your video {videoName} has been published.', language, { videoName: this.payload.name }),
locals: {
- title: 'Your video is live',
+ title: t('Your video is live', language),
action: {
- text: 'View video',
+ text: t('View video', language),
url: videoUrl
}
}
diff --git a/server/core/lib/notifier/shared/video-publication/import-finished-for-owner.ts b/server/core/lib/notifier/shared/video-publication/import-finished-for-owner.ts
index 38f12d8cf..f8fb50f81 100644
--- a/server/core/lib/notifier/shared/video-publication/import-finished-for-owner.ts
+++ b/server/core/lib/notifier/shared/video-publication/import-finished-for-owner.ts
@@ -1,9 +1,11 @@
+import { To, UserNotificationType } from '@peertube/peertube-models'
+import { t } from '@server/helpers/i18n.js'
import { logger } from '@server/helpers/logger.js'
import { WEBSERVER } from '@server/initializers/constants.js'
-import { UserModel } from '@server/models/user/user.js'
+import { myVideoImportsUrl } from '@server/lib/client-urls.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
import { MUserDefault, MUserWithNotificationSetting, MVideoImportVideo, UserNotificationModelForApi } from '@server/types/models/index.js'
-import { UserNotificationType } from '@peertube/peertube-models'
import { AbstractNotification } from '../common/abstract-notification.js'
export type ImportFinishedForOwnerPayload = {
@@ -11,7 +13,7 @@ export type ImportFinishedForOwnerPayload = {
success: boolean
}
-export class ImportFinishedForOwner extends AbstractNotification {
+export class ImportFinishedForOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -46,46 +48,47 @@ export class ImportFinishedForOwner extends AbstractNotification ${importUrl}.`
+ const text = t('Your video import {targetId} encountered an error.', language, { targetId })
return {
to,
- subject: `Your video import "${this.videoImport.getTargetIdentifier()}" encountered an error`,
+ subject: t('Your video import encountered an error', language),
text,
locals: {
- title: 'Import failed',
+ title: t('Import failed', language),
action: {
- text: 'Review imports',
- url: importUrl
+ text: t('Review imports', language),
+ url: myVideoImportsUrl
}
}
}
diff --git a/server/core/lib/notifier/shared/video-publication/new-video-or-live-for-subscribers.ts b/server/core/lib/notifier/shared/video-publication/new-video-or-live-for-subscribers.ts
index 1940a55d6..1b5905330 100644
--- a/server/core/lib/notifier/shared/video-publication/new-video-or-live-for-subscribers.ts
+++ b/server/core/lib/notifier/shared/video-publication/new-video-or-live-for-subscribers.ts
@@ -1,12 +1,13 @@
+import { To, UserNotificationType, VideoPrivacy, VideoState } from '@peertube/peertube-models'
import { logger } from '@server/helpers/logger.js'
import { WEBSERVER } from '@server/initializers/constants.js'
-import { UserModel } from '@server/models/user/user.js'
import { UserNotificationModel } from '@server/models/user/user-notification.js'
+import { UserModel } from '@server/models/user/user.js'
import { MUserWithNotificationSetting, MVideoAccountLight, UserNotificationModelForApi } from '@server/types/models/index.js'
-import { UserNotificationType, VideoPrivacy, VideoState } from '@peertube/peertube-models'
import { AbstractNotification } from '../common/abstract-notification.js'
+import { t } from '@server/helpers/i18n.js'
-export class NewVideoOrLiveForSubscribers extends AbstractNotification {
+export class NewVideoOrLiveForSubscribers extends AbstractNotification {
private users: MUserWithNotificationSetting[]
async prepare () {
@@ -50,7 +51,9 @@ export class NewVideoOrLiveForSubscribers extends AbstractNotification {
+export class StudioEditionFinishedForOwner extends AbstractNotification {
private user: MUserDefault
async prepare () {
@@ -38,17 +39,18 @@ export class StudioEditionFinishedForOwner extends AbstractNotification a.toFormattedJSON()),
banners: serverActor.Banners.map(b => b.toFormattedJSON()),
@@ -512,6 +514,24 @@ class ServerConfigManager {
return maxBy(this.getOpenGraphLogos(serverActor), 'width')
}
+ getLogoUrl (serverActor: MActorUploadImages, width: 192 | 512) {
+ const customLogo = this.getLogo(serverActor, width)
+
+ if (customLogo) {
+ return WEBSERVER.URL + customLogo.getStaticPath()
+ }
+
+ return `${WEBSERVER.URL}/client/assets/images/icons/icon-${width}x${width}.png`
+ }
+
+ getLogo (serverActor: MActorUploadImages, width: 192 | 512) {
+ if (serverActor.Avatars.length > 0) {
+ return findAppropriateImage(serverActor.Avatars, width)
+ }
+
+ return undefined
+ }
+
private getFaviconLogos (serverActor: MActorUploadImages) {
return this.getLogoWithFallbacks({
serverActor,
diff --git a/server/core/lib/user-import-export/exporters/user-settings-exporter.ts b/server/core/lib/user-import-export/exporters/user-settings-exporter.ts
index f63590493..ff6d2d702 100644
--- a/server/core/lib/user-import-export/exporters/user-settings-exporter.ts
+++ b/server/core/lib/user-import-export/exporters/user-settings-exporter.ts
@@ -1,8 +1,7 @@
import { AbstractUserExporter } from './abstract-user-exporter.js'
import { UserSettingsExportJSON } from '@peertube/peertube-models'
-export class UserSettingsExporter extends AbstractUserExporter {
-
+export class UserSettingsExporter extends AbstractUserExporter {
export () {
return {
json: {
@@ -19,6 +18,7 @@ export class UserSettingsExporter extends AbstractUserExporter
@@ -46,6 +48,7 @@ export class UserSettingsImporter extends AbstractUserImporter {
@Column
autoPlayNextVideoPlaylist: boolean
+ @AllowNull(true)
+ @Column(DataType.STRING)
+ language: string
+
@AllowNull(true)
@Default(null)
@Is('UserVideoLanguages', value => throwIfNotValid(value, isUserVideoLanguages, 'video languages'))
@@ -872,6 +876,16 @@ export class UserModel extends SequelizeModel {
return UserModel.unscoped().findOne(query)
}
+ static async loadForEmail (id: number) {
+ const user = await UserModel.unscoped().findByPk(id)
+
+ if (!user) return undefined
+
+ return { email: user.email, language: user.getLanguage() }
+ }
+
+ // ---------------------------------------------------------------------------
+
static generateUserQuotaBaseSQL (options: {
daily: boolean
whereUserId: '$userId' | '"UserModel"."id"'
@@ -981,6 +995,10 @@ export class UserModel extends SequelizeModel {
return comparePassword(password, this.password)
}
+ getLanguage () {
+ return this.language || CONFIG.INSTANCE.DEFAULT_LANGUAGE
+ }
+
toFormattedJSON (this: MUserFormattable, parameters: { withAdminFlags?: boolean } = {}): User {
const videoQuotaUsed = this.get('videoQuotaUsed')
const videoQuotaUsedDaily = this.get('videoQuotaUsedDaily')
@@ -1026,6 +1044,8 @@ export class UserModel extends SequelizeModel {
autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist,
videoLanguages: this.videoLanguages,
+ language: this.getLanguage(),
+
role: {
id: this.role,
label: USER_ROLE_LABELS[this.role]
diff --git a/server/core/types/express.d.ts b/server/core/types/express.d.ts
index 63f5248d3..91240eba4 100644
--- a/server/core/types/express.d.ts
+++ b/server/core/types/express.d.ts
@@ -56,6 +56,8 @@ declare module 'express' {
query: any
method: HttpMethodType
rawBody: Buffer // Allow plugin routes to access the raw body
+
+ t: (key: string, context?: Record) => string
}
// ---------------------------------------------------------------------------
diff --git a/server/locales/ar/translation.json b/server/locales/ar/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/ar/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/ca-ES/translation.json b/server/locales/ca-ES/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/ca-ES/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/cs-CZ/translation.json b/server/locales/cs-CZ/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/cs-CZ/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/de-DE/translation.json b/server/locales/de-DE/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/de-DE/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/el-GR/translation.json b/server/locales/el-GR/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/el-GR/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/en-US/translation.json b/server/locales/en-US/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/en-US/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/eo/translation.json b/server/locales/eo/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/eo/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/es-ES/translation.json b/server/locales/es-ES/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/es-ES/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/eu-ES/translation.json b/server/locales/eu-ES/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/eu-ES/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/fa-IR/translation.json b/server/locales/fa-IR/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/fa-IR/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/fi-FI/translation.json b/server/locales/fi-FI/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/fi-FI/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/fr-FR/translation.json b/server/locales/fr-FR/translation.json
new file mode 100644
index 000000000..1a5e12695
--- /dev/null
+++ b/server/locales/fr-FR/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "Nouveau message sur le signalement",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "Un nouveau message de {messageAccountName} a été publié sur le signalement #{abuseId} ",
+ "Abuse report state changed": "État du signalement modifié",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Votre signalement #{abuseId} sur {instanceName} a été accepté.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Votre signalement #{abuseId} sur {instanceName} a été rejeté.",
+ "An account is pending moderation": "Un compte est en attente de modération",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} a reçu un signalement pour le compte : {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} a reçu un signalement pour le compte distant : {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "Le signaleur, {reporter}, a cité la/les raison(s) suivante(s) :",
+ "Someone just used the contact form": "Quelqu'un a utilisé le formulaire de contact",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} vous a envoyé un message via le formulaire de contact de {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "Vous pouvez contacter la personne à l'adresse {fromEmail} , ou simplement répondre à cet e-mail.",
+ "New follower on your channel": "Nouvel abonné de votre chaîne",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Votre compte {followingName} a un nouvel abonné : {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Votre chaîne {followingName} a un nouvel abonné : {followerName} .",
+ "Your account has been blocked": "Votre compte a été bloqué",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Votre compte {username} a été bloqué par les modérateurs de {instanceName} pour la raison suivante :",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Votre compte {username} a été bloqué par les modérateurs de {instanceName}.",
+ "Your account has been unblocked": "Votre compte a été débloqué",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Votre compte {username} a été débloqué par les modérateurs de {instanceName}.",
+ "Hi {username},": "Bonjour {username},",
+ "View in your notifications": "Voir dans vos notifications",
+ "Manage your notification preferences in your profile": "Gérer vos préférences de notification dans votre profil",
+ "Password creation for your account": "Création de mot de passe pour votre compte",
+ "Welcome to {instanceName} !": "Bienvenue sur {instanceName} !",
+ "Your username is: {username}.": "Votre nom d'utilisateur est : {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Veuillez cliquer sur le lien ci-dessous pour définir votre mot de passe (ce lien expirera dans sept jours) :",
+ "Create my password": "Créer mon mot de passe",
+ "Password reset for your account": "Réinitialisation de mot de passe pour votre compte",
+ "A reset password procedure for your account has been requested on {instanceName}.": "Une procédure de réinitialisation de mot de passe pour votre compte a été demandée sur {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Veuillez cliquer sur le lien ci-dessous pour le réinitialiser (le lien expirera dans 1 heure) :",
+ "Reset my password": "Réinitialiser mon mot de passe",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "Si vous n'êtes pas la personne qui a initié cette demande, veuillez nous le faire savoir en répondant à cet e-mail.",
+ "New PeerTube version available": "Nouvelle version de PeerTube disponible",
+ "A new version of PeerTube is available: {latestVersion}.": "Une nouvelle version de PeerTube est disponible : {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "Vous pouvez consulter les dernières actualités sur JoinPeerTube .",
+ "New plugin version available": "Nouvelle version de plugin disponible",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "Une nouvelle version du plugin {pluginName} est disponible : {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "Une nouvelle version du thème {pluginName} est disponible : {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "Vous voudrez peut-être faire la mise à jour sur votre interface d'administration .",
+ "Your export archive has been created": "Votre archive d'exportation a été créée",
+ "Your export archive has been created.": "Votre archive d'exportation a été créée.",
+ "You can download it in your account export page .": "Vous pouvez la télécharger dans votre page d'exportation de compte .",
+ "Failed to create your export archive": "Échec de la création de votre archive d'exportation",
+ "We are sorry but the generation of your export archive has failed:": "Nous sommes désolés mais la génération de votre archive d'exportation a échouée :",
+ "Please contact your administrator if the problem occurs again.": "Veuillez contacter votre administrateur si le problème se reproduit.",
+ "Your archive import has finished": "L'importation de votre archive est terminée",
+ "Imported: {success}": "Importé : {success}",
+ "Not imported as considered duplicate: {duplicates}": "Non importé car considéré comme doublon : {duplicates}",
+ "Not imported due to error: {errors}": "Non importé en raison d'une erreur : {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "L'importation de votre archive est terminée. Voici le résumé des objets importés :",
+ "User settings:": "Paramètres utilisateur :",
+ "Account (name, description, avatar...):": "Compte (nom, description, avatar...) :",
+ "Blocklist:": "Liste de blocage :",
+ "Channels:": "Chaînes :",
+ "Likes:": "J'aime :",
+ "Dislikes:": "Je n'aime pas :",
+ "Subscriptions:": "Abonnements :",
+ "Video Playlists:": "Playlists vidéo :",
+ "Videos:": "Vidéos :",
+ "Video history:": "Historique vidéo :",
+ "Watched Words Lists:": "Listes de mots surveillés :",
+ "Comment auto tag policies:": "Politiques d'auto-étiquetage des commentaires :",
+ "Failed to import your archive": "Échec de l'importation de votre archive",
+ "We are sorry but the import of your archive has failed:": "Nous sommes désolés mais l'importation de votre archive a échoué :",
+ "A new user registered": "Un nouvel utilisateur s'est inscrit",
+ "User {userUsername} just registered.": "L'utilisateur {userUsername} vient de s'inscrire.",
+ "You might want to contact them at {userEmail} .": "Vous pourriez vouloir contacter l'utilisateur via {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "Vous pourriez vouloir contacter l'utilisateur via {userEmail} (l'e-mail n'a pas encore été vérifié).",
+ "Congratulation {username}, your registration request has been accepted!": "Félicitations {username}, votre demande d'inscription a été acceptée !",
+ "Your registration request has been accepted.": "Votre demande d'inscription a été acceptée.",
+ "Moderators sent you the following message:": "Les modérateurs vous ont envoyé le message suivant :",
+ "Registration request of your account {username} has rejected": "La demande d'inscription de votre compte {username} a été rejetée",
+ "Your registration request has been rejected.": "Votre demande d'inscription a été rejetée.",
+ "A new user wants to register": "Un nouvel utilisateur souhaite s'inscrire",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Vérification d'e-mail",
+ "You requested an account on {instanceName} .": "Vous avez demandé un compte sur {instanceName} .",
+ "To complete your registration request you must verify your email first!": "Pour compléter votre demande d'inscription, vous devez d'abord vérifier votre e-mail !",
+ "You created an account on {instanceName} .": "Vous avez créé un compte sur {instanceName} .",
+ "To start using your account you must verify your email first!": "Pour commencer à utiliser votre compte, vous devez d'abord vérifier votre e-mail !",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Veuillez cliquer sur le lien ci-dessous pour vérifier que cet e-mail vous appartient (le lien expirera dans 1 heure) :",
+ "Verify my email": "Vérifier mon e-mail",
+ "You requested to change your email.": "Vous avez demandé à changer votre e-mail.",
+ "A video is pending moderation": "Une vidéo est en attente de modération",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} a reçu un signalement pour la vidéo {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} a reçu un signalement pour la vidéo distante {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "La vidéo a été mise en ligne par la chaîne {channelDisplayName} .",
+ "It was published on {videoPublishedAt}.": "Elle a été publiée le {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "Elle a été mise en ligne le {videoCreatedAt} mais n'est pas encore publiée.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "Une vidéo récemment ajoutée a été automatiquement bloquée et nécessite une révision par un modérateur avant d'être rendue publique : {videoName} par {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "En dehors du propriétaire et de l'équipe de modération, personne ne pourra voir la vidéo tant que vous ne la débloquez pas.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "Si vous faites confiance au propriétaire, tout administrateur peut mettre l'utilisateur sur liste blanche pour les prochaines vidéos afin qu'elles ne nécessitent pas d'approbation avant d'être rendues publiques.",
+ "A comment is pending moderation": "Un commentaire est en attente de modération",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} a reçu un signalement pour le commentaire sur la vidéo {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} a reçu un signalement pour le commentaire distant sur la vidéo {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "Le commentaire a été publié le {commentCreatedAt} par {flaggedAccount} .",
+ "Someone mentioned you": "Quelqu'un vous a mentionné",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} vous a mentionné dans un commentaire de la vidéo {videoName} :",
+ "Someone commented your video": "Quelqu'un a commenté votre vidéo",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} a ajouté un commentaire sur votre vidéo {videoName} :",
+ "This comment requires approval.": "Ce commentaire nécessite une approbation.",
+ "Your video has been blocked": "Votre vidéo a été bloquée",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Votre vidéo {videoName} a été bloquée par les modérateurs de {instanceName} pour la raison suivante :",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Votre vidéo {videoName} a été bloquée par les modérateurs de {instanceName}.",
+ "Your video has been unblocked": "Votre vidéo a été débloquée",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Votre vidéo {videoName} a été débloquée par les modérateurs de {instanceName}.",
+ "Reset your account password": "Réinitialiser le mot de passe de votre compte",
+ "Create your account password": "Créer le mot de passe de votre compte",
+ "Verify your email on {instanceName}": "Vérifiez votre e-mail sur {instanceName}",
+ "Contact form - {subject}": "Formulaire de contact - {subject}",
+ "Your registration request for {username} has been accepted": "Votre demande d'inscription pour {username} a été acceptée",
+ "Login to your account": "Connectez-vous à votre compte",
+ "Your registration request for {username} has been rejected": "Votre demande d'inscription pour {username} a été rejetée",
+ "New message on report #{id}": "Nouveau message sur le signalement #{id}",
+ "View report #{id}": "Voir le signalement #{id}",
+ "Report #{id} has been accepted": "Le signalement #{id} a été accepté",
+ "Report #{id} has been rejected": "Le signalement #{id} a été rejeté",
+ "New video abuse report from {reporter}": "Nouveau signalement vidéo de {reporter}",
+ "New comment abuse report from {reporter}": "Nouveau signalement de commentaire de {reporter}",
+ "New account abuse report from {reporter}": "Nouveau signalement de compte de {reporter}",
+ "A new video is pending moderation": "Une nouvelle vidéo est en attente de modération",
+ "Review video": "Examiner la vidéo",
+ "View video": "Voir la vidéo",
+ "Transcription of your video has been generated": "La transcription de votre vidéo a été générée",
+ "Transcription in {language} of your video {videoName} has been generated.": "La transcription en {language} de votre vidéo {videoName} a été générée.",
+ "Mention on video {videoName}": "Mention sur la vidéo {videoName}",
+ "View comment": "Voir le commentaire",
+ "New comment on your video": "Nouveau commentaire sur votre vidéo",
+ "Review comment": "Examiner le commentaire",
+ "Auto platform follow": "Abonnement de automatique de plateforme",
+ "View subscription": "Voir l'abonnement",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} a un nouvel abonné, {followerUrl}, en attente d'approbation.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} a un nouvel abonné : {followerUrl}.",
+ "New follower for {instanceName}": "Nouvel abonné pour {instanceName}",
+ "Review followers": "Examiner les abonnés",
+ "New follower on your account {followingName}": "Nouvel abonné sur votre compte {followingName}",
+ "New follower on your channel {followingName}": "Nouvel abonné sur votre chaîne {followingName}",
+ "A new user registered on {instanceName}": "Un nouvel utilisateur s'est inscrit sur {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "Une nouvelle version de PeerTube est disponible : {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "Une nouvelle version du plugin {pluginName} est disponible : {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "Une nouvelle version du thème {pluginName} est disponible : {latestVersion}",
+ "A new user wants to register: {username}": "Un nouvel utilisateur souhaite s'inscrire : {username}",
+ "View registration request": "Voir la demande d'inscription",
+ "Your video has been published": "Votre vidéo a été publiée",
+ "Your video {videoName} has been published.": "Votre vidéo {videoName} a été publiée.",
+ "Your video is live": "Votre vidéo est en ligne",
+ "Your video import is complete": "L'importation de votre vidéo est terminée",
+ "Your video {targetId} has just finished importing.": "Votre vidéo {targetId} vient de terminer son importation.",
+ "Your video import targetId encountered an error.": "L'importation de votre vidéo {targetId} a rencontré une erreur.",
+ "Your video import encountered an error": "L'importation de votre vidéo a rencontré une erreur",
+ "Import failed": "Échec de l'importation",
+ "Review imports": "Examiner les importations",
+ "{channelName} is live streaming": "{channelName} est en direct",
+ "Your subscription {channelName} is live streaming {videoName}": "Votre abonnement {channelName} diffuse en direct {videoName}",
+ "Edition of your video has finished": "L'édition de votre vidéo est terminée",
+ "Edition of your video {videoName} has finished.": "L'édition de votre vidéo {videoName} est terminée.",
+ "Video edition has finished": "L'édition de la vidéo est terminée"
+}
diff --git a/server/locales/gd/translation.json b/server/locales/gd/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/gd/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/gl-ES/translation.json b/server/locales/gl-ES/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/gl-ES/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/hr/translation.json b/server/locales/hr/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/hr/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/hu-HU/translation.json b/server/locales/hu-HU/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/hu-HU/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/is/translation.json b/server/locales/is/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/is/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/it-IT/translation.json b/server/locales/it-IT/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/it-IT/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/ja-JP/translation.json b/server/locales/ja-JP/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/ja-JP/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/kab/translation.json b/server/locales/kab/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/kab/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/nb-NO/translation.json b/server/locales/nb-NO/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/nb-NO/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/nl-NL/translation.json b/server/locales/nl-NL/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/nl-NL/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/nn/translation.json b/server/locales/nn/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/nn/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/oc/translation.json b/server/locales/oc/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/oc/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/pl-PL/translation.json b/server/locales/pl-PL/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/pl-PL/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/pt-BR/translation.json b/server/locales/pt-BR/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/pt-BR/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/pt-PT/translation.json b/server/locales/pt-PT/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/pt-PT/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/ru-RU/translation.json b/server/locales/ru-RU/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/ru-RU/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/sk-SK/translation.json b/server/locales/sk-SK/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/sk-SK/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/sq/translation.json b/server/locales/sq/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/sq/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/sv-SE/translation.json b/server/locales/sv-SE/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/sv-SE/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/th-TH/translation.json b/server/locales/th-TH/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/th-TH/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/tok/translation.json b/server/locales/tok/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/tok/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/tr-TR/translation.json b/server/locales/tr-TR/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/tr-TR/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/uk-UA/translation.json b/server/locales/uk-UA/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/uk-UA/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/vi-VN/translation.json b/server/locales/vi-VN/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/vi-VN/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/zh-Hans-CN/translation.json b/server/locales/zh-Hans-CN/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/zh-Hans-CN/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/locales/zh-Hant-TW/translation.json b/server/locales/zh-Hant-TW/translation.json
new file mode 100644
index 000000000..dfdcef08b
--- /dev/null
+++ b/server/locales/zh-Hant-TW/translation.json
@@ -0,0 +1,160 @@
+{
+ "New message on abuse report": "New message on abuse report",
+ "A new message by {messageAccountName} was posted on abuse report #{abuseId} ": "A new message by {messageAccountName} was posted on abuse report #{abuseId} ",
+ "Abuse report state changed": "Abuse report state changed",
+ "Your abuse report #{abuseId} on {instanceName} has been accepted.": "Your abuse report #{abuseId} on {instanceName} has been accepted.",
+ "Your abuse report #{abuseId} on {instanceName} has been rejected.": "Your abuse report #{abuseId} on {instanceName} has been rejected.",
+ "An account is pending moderation": "An account is pending moderation",
+ "{instanceName} received an abuse report for the account: {accountDisplayName} ": "{instanceName} received an abuse report for the account: {accountDisplayName} ",
+ "{instanceName} received an abuse report for the remote account: {accountDisplayName} ": "{instanceName} received an abuse report for the remote account: {accountDisplayName} ",
+ "The reporter, {reporter}, cited the following reason(s):": "The reporter, {reporter}, cited the following reason(s):",
+ "Someone just used the contact form": "Someone just used the contact form",
+ "{fromName} sent you a message via the contact form on {instanceName} : ": "{fromName} sent you a message via the contact form on {instanceName} : ",
+ "You can contact them at {fromEmail} , or simply reply to this email to get in touch.": "You can contact them at {fromEmail} , or simply reply to this email to get in touch.",
+ "New follower on your channel": "New follower on your channel",
+ "Your account {followingName} has a new subscriber: {followerName} .": "Your account {followingName} has a new subscriber: {followerName} .",
+ "Your channel {followingName} has a new subscriber: {followerName} .": "Your channel {followingName} has a new subscriber: {followerName} .",
+ "Your account has been blocked": "Your account has been blocked",
+ "Your account {username} has been blocked by {instanceName} moderators for the following reason:": "Your account {username} has been blocked by {instanceName} moderators for the following reason:",
+ "Your account {username} has been blocked by {instanceName} moderators.": "Your account {username} has been blocked by {instanceName} moderators.",
+ "Your account has been unblocked": "Your account has been unblocked",
+ "Your account {username} has been unblocked by {instanceName} moderators.": "Your account {username} has been unblocked by {instanceName} moderators.",
+ "Hi {username},": "Hi {username},",
+ "View in your notifications": "View in your notifications",
+ "Manage your notification preferences in your profile": "Manage your notification preferences in your profile",
+ "Password creation for your account": "Password creation for your account",
+ "Welcome to {instanceName} !": "Welcome to {instanceName} !",
+ "Your username is: {username}.": "Your username is: {username}.",
+ "Please click on the link below to set your password (this link will expire within seven days):": "Please click on the link below to set your password (this link will expire within seven days):",
+ "Create my password": "Create my password",
+ "Password reset for your account": "Password reset for your account",
+ "A reset password procedure for your account has been requested on {instanceName}.": "A reset password procedure for your account has been requested on {instanceName}.",
+ "Please click on the link below to reset it (the link will expire within 1 hour):": "Please click on the link below to reset it (the link will expire within 1 hour):",
+ "Reset my password": "Reset my password",
+ "If you are not the person who initiated this request, please let us know by replying to this email.": "If you are not the person who initiated this request, please let us know by replying to this email.",
+ "New PeerTube version available": "New PeerTube version available",
+ "A new version of PeerTube is available: {latestVersion}.": "A new version of PeerTube is available: {latestVersion}.",
+ "You can check the latest news on JoinPeerTube .": "You can check the latest news on JoinPeerTube .",
+ "New plugin version available": "New plugin version available",
+ "A new version of the plugin {pluginName} is available: {latestVersion}.": "A new version of the plugin {pluginName} is available: {latestVersion}.",
+ "A new version of the theme {pluginName} is available: {latestVersion}.": "A new version of the theme {pluginName} is available: {latestVersion}.",
+ "You might want to upgrade it on your admin interface .": "You might want to upgrade it on your admin interface .",
+ "Your export archive has been created": "Your export archive has been created",
+ "Your export archive has been created.": "Your export archive has been created.",
+ "You can download it in your account export page .": "You can download it in your account export page .",
+ "Failed to create your export archive": "Failed to create your export archive",
+ "We are sorry but the generation of your export archive has failed:": "We are sorry but the generation of your export archive has failed:",
+ "Please contact your administrator if the problem occurs again.": "Please contact your administrator if the problem occurs again.",
+ "Your archive import has finished": "Your archive import has finished",
+ "Imported: {success}": "Imported: {success}",
+ "Not imported as considered duplicate: {duplicates}": "Not imported as considered duplicate: {duplicates}",
+ "Not imported due to error: {errors}": "Not imported due to error: {errors}",
+ "Your archive import has finished. Here is the summary of imported objects:": "Your archive import has finished. Here is the summary of imported objects:",
+ "User settings:": "User settings:",
+ "Account (name, description, avatar...):": "Account (name, description, avatar...):",
+ "Blocklist:": "Blocklist:",
+ "Channels:": "Channels:",
+ "Likes:": "Likes:",
+ "Dislikes:": "Dislikes:",
+ "Subscriptions:": "Subscriptions:",
+ "Video Playlists:": "Video Playlists:",
+ "Videos:": "Videos:",
+ "Video history:": "Video history:",
+ "Watched Words Lists:": "Watched Words Lists:",
+ "Comment auto tag policies:": "Comment auto tag policies:",
+ "Failed to import your archive": "Failed to import your archive",
+ "We are sorry but the import of your archive has failed:": "We are sorry but the import of your archive has failed:",
+ "A new user registered": "A new user registered",
+ "User {userUsername} just registered.": "User {userUsername} just registered.",
+ "You might want to contact them at {userEmail} .": "You might want to contact them at {userEmail} .",
+ "You might want to contact them at {userEmail} (the email has not been verified yet).": "You might want to contact them at {userEmail} (the email has not been verified yet).",
+ "Congratulation {username}, your registration request has been accepted!": "Congratulation {username}, your registration request has been accepted!",
+ "Your registration request has been accepted.": "Your registration request has been accepted.",
+ "Moderators sent you the following message:": "Moderators sent you the following message:",
+ "Registration request of your account {username} has rejected": "Registration request of your account {username} has rejected",
+ "Your registration request has been rejected.": "Your registration request has been rejected.",
+ "A new user wants to register": "A new user wants to register",
+ "User {registrationUsername} wants to register on {instanceName} for the following reason:": "User {registrationUsername} wants to register on {instanceName} for the following reason:",
+ "Email verification": "Email verification",
+ "You requested an account on {instanceName} .": "You requested an account on {instanceName} .",
+ "To complete your registration request you must verify your email first!": "To complete your registration request you must verify your email first!",
+ "You created an account on {instanceName} .": "You created an account on {instanceName} .",
+ "To start using your account you must verify your email first!": "To start using your account you must verify your email first!",
+ "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):": "Please click on the link below to verify this email belongs to you (the link will expire within 1 hour):",
+ "Verify my email": "Verify my email",
+ "You requested to change your email.": "You requested to change your email.",
+ "A video is pending moderation": "A video is pending moderation",
+ "{instanceName} received an abuse report for the video {videoName} .": "{instanceName} received an abuse report for the video {videoName} .",
+ "{instanceName} received an abuse report for the remote video {videoName} .": "{instanceName} received an abuse report for the remote video {videoName} .",
+ "The video was uploaded by {channelDisplayName} channel.": "The video was uploaded by {channelDisplayName} channel.",
+ "It was published on {videoPublishedAt}.": "It was published on {videoPublishedAt}.",
+ "It was uploaded on {videoCreatedAt} but not yet published.": "It was uploaded on {videoCreatedAt} but not yet published.",
+ "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .": "A recently added video was automatically blocked and requires moderator review before going public: {videoName} by {channelDisplayName} .",
+ "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.": "Apart from the publisher and the moderation team, no one will be able to see the video until you unblock it.",
+ "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.": "If you trust the publisher, any admin can whitelist the user for later videos so that they don't require approval before going public.",
+ "A comment is pending moderation": "A comment is pending moderation",
+ "{instanceName} received an abuse report for the comment on video {videoName} .": "{instanceName} received an abuse report for the comment on video {videoName} .",
+ "{instanceName} received an abuse report for the remote comment on video {videoName} .": "{instanceName} received an abuse report for the remote comment on video {videoName} .",
+ "The comment was posted on {commentCreatedAt} by {flaggedAccount} .": "The comment was posted on {commentCreatedAt} by {flaggedAccount} .",
+ "Someone mentioned you": "Someone mentioned you",
+ "{accountName} mentioned you in a comment on video {videoName} :": "{accountName} mentioned you in a comment on video {videoName} :",
+ "Someone commented your video": "Someone commented your video",
+ "{accountName} added a comment on your video {videoName} :": "{accountName} added a comment on your video {videoName} :",
+ "This comment requires approval.": "This comment requires approval.",
+ "Your video has been blocked": "Your video has been blocked",
+ "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:": "Your video {videoName} has been blocked by {instanceName} moderators for the following reason:",
+ "Your video {videoName} has been blocked by {instanceName} moderators.": "Your video {videoName} has been blocked by {instanceName} moderators.",
+ "Your video has been unblocked": "Your video has been unblocked",
+ "Your video {videoName} has been unblocked by {instanceName} moderators.": "Your video {videoName} has been unblocked by {instanceName} moderators.",
+ "Reset your account password": "Reset your account password",
+ "Create your account password": "Create your account password",
+ "Verify your email on {instanceName}": "Verify your email on {instanceName}",
+ "Contact form - {subject}": "Contact form - {subject}",
+ "Your registration request for {username} has been accepted": "Your registration request for {username} has been accepted",
+ "Login to your account": "Login to your account",
+ "Your registration request for {username} has been rejected": "Your registration request for {username} has been rejected",
+ "New message on report #{id}": "New message on report #{id}",
+ "View report #{id}": "View report #{id}",
+ "Report #{id} has been accepted": "Report #{id} has been accepted",
+ "Report #{id} has been rejected": "Report #{id} has been rejected",
+ "New video abuse report from {reporter}": "New video abuse report from {reporter}",
+ "New comment abuse report from {reporter}": "New comment abuse report from {reporter}",
+ "New account abuse report from {reporter}": "New account abuse report from {reporter}",
+ "A new video is pending moderation": "A new video is pending moderation",
+ "Review video": "Review video",
+ "View video": "View video",
+ "Transcription of your video has been generated": "Transcription of your video has been generated",
+ "Transcription in {language} of your video {videoName} has been generated.": "Transcription in {language} of your video {videoName} has been generated.",
+ "Mention on video {videoName}": "Mention on video {videoName}",
+ "View comment": "View comment",
+ "New comment on your video": "New comment on your video",
+ "Review comment": "Review comment",
+ "Auto platform follow": "Auto platform follow",
+ "View subscription": "View subscription",
+ "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.": "{instanceName} has a new follower, {followerUrl}, awaiting manual approval.",
+ "{instanceName} has a new follower: {followerUrl}.": "{instanceName} has a new follower: {followerUrl}.",
+ "New follower for {instanceName}": "New follower for {instanceName}",
+ "Review followers": "Review followers",
+ "New follower on your account {followingName}": "New follower on your account {followingName}",
+ "New follower on your channel {followingName}": "New follower on your channel {followingName}",
+ "A new user registered on {instanceName}": "A new user registered on {instanceName}",
+ "A new PeerTube version is available: {latestVersion}": "A new PeerTube version is available: {latestVersion}",
+ "A new version of the plugin {pluginName} is available: {latestVersion}": "A new version of the plugin {pluginName} is available: {latestVersion}",
+ "A new version of the theme {pluginName} is available: {latestVersion}": "A new version of the theme {pluginName} is available: {latestVersion}",
+ "A new user wants to register: {username}": "A new user wants to register: {username}",
+ "View registration request": "View registration request",
+ "Your video has been published": "Your video has been published",
+ "Your video {videoName} has been published.": "Your video {videoName} has been published.",
+ "Your video is live": "Your video is live",
+ "Your video import is complete": "Your video import is complete",
+ "Your video {targetId} has just finished importing.": "Your video {targetId} has just finished importing.",
+ "Your video import targetId encountered an error.": "Your video import targetId encountered an error.",
+ "Your video import encountered an error": "Your video import encountered an error",
+ "Import failed": "Import failed",
+ "Review imports": "Review imports",
+ "{channelName} is live streaming": "{channelName} is live streaming",
+ "Your subscription {channelName} is live streaming {videoName}": "Your subscription {channelName} is live streaming {videoName}",
+ "Edition of your video has finished": "Edition of your video has finished",
+ "Edition of your video {videoName} has finished.": "Edition of your video {videoName} has finished.",
+ "Video edition has finished": "Video edition has finished"
+}
diff --git a/server/server.ts b/server/server.ts
index eca0dd13f..ebf8c3391 100644
--- a/server/server.ts
+++ b/server/server.ts
@@ -10,6 +10,7 @@ import { checkMissedConfig, checkFFmpeg, checkNodeVersion } from './core/initial
import { CONFIG } from './core/initializers/config.js'
import { API_VERSION, WEBSERVER, loadLanguages } from './core/initializers/constants.js'
import { logger } from './core/helpers/logger.js'
+import { initI18n, useI18n } from '@server/helpers/i18n.js'
const missed = checkMissedConfig()
if (missed.length !== 0) {
@@ -55,8 +56,10 @@ migrate()
})
// ----------- Initialize -----------
-loadLanguages()
- .catch(err => logger.error('Cannot load languages', { err }))
+Promise.all([
+ initI18n(),
+ loadLanguages()
+]).catch(err => logger.error('Cannot load i18n/languages', { err }))
// Express configuration
import express from 'express'
@@ -83,6 +86,8 @@ app.use((_req, res, next) => {
return next()
})
+app.use(useI18n)
+
// Security middleware
import { baseCSP } from './core/middlewares/csp.js'
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml
index d84d89306..b0b52652e 100644
--- a/support/doc/api/openapi.yaml
+++ b/support/doc/api/openapi.yaml
@@ -309,6 +309,8 @@ tags:
Manage runner registration token
- name: Video Passwords
description: Operation on video passwords
+ - name: Client Config
+ description: Configuration of the web client
x-tagGroups:
- name: Static endpoints
@@ -367,6 +369,7 @@ x-tagGroups:
- name: Instance
tags:
- Config
+ - Client Config
- Homepage
- Instance Follows
- Instance Redundancy
@@ -7321,6 +7324,28 @@ paths:
responses:
'204':
description: successful operation
+ /api/v1/client-config/update-language:
+ post:
+ tags:
+ - Client Config
+ summary: Update client language
+ description: Set a cookie so that, the next time the client refreshes the HTML of the web interface, PeerTube will use the next language
+ operationId: updateClientLanguage
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ language:
+ type: string
+ description: Language code to set
+ example: 'en-US'
+ required:
+ - language
+ responses:
+ '204':
+ description: successful operation
servers:
- url: 'https://peertube2.cpy.re'
@@ -9491,6 +9516,8 @@ components:
type: string
serverCountry:
type: string
+ defaultLanguage:
+ type: string
support:
type: object
properties:
@@ -10674,6 +10701,9 @@ components:
items:
type: string
description: list of languages to filter videos down to
+ language:
+ type: string
+ description: default language for this user
theme:
type: string
noInstanceConfigWarningModal:
diff --git a/support/doc/translation.md b/support/doc/translation.md
index 3852865cc..fa222fa7e 100644
--- a/support/doc/translation.md
+++ b/support/doc/translation.md
@@ -14,7 +14,7 @@ You can get a chance to see translations before the official release by going to
* Create an account: https://weblate.framasoft.org/accounts/register/
* Validate your email and follow the link sent
- * Create your password (keep the `Current password` field empty) and setup your account
+ * Create your password (keep the `Current password` field empty) and set up your account
* To translate the PeerTube web, visit the PeerTube project page: https://weblate.framasoft.org/projects/peertube/
* To translate the PeerTube mobile application, visit the PeerTube App project page: https://weblate.framasoft.org/projects/peertube-app/
* Choose the file and the locale you want to translate
@@ -26,8 +26,8 @@ There are 4 files:
* **angular**: contains client strings
* **player**: contains player strings.
Most of the strings come from VideoJS, so you can help yourself by using [video.js JSON files](https://github.com/videojs/video.js/tree/master/lang)
- * **server**: contains server strings (privacies, licences...) and iso639 (languages) strings used by PeerTube to describe the audio language of a particular video.
- It's the reason why these strings should be translated too. There are many strings so do not hesitate to translate only main audio languages.
+ * **server**: contains server strings clients can fetch in JSON format so they don't have to translate common PeerTube strings themselves (iso639 languages, privacies, licences...)
+ * **server-internal**: contains internal server strings used in the REST API responses or emails
## Tips
@@ -41,7 +41,7 @@ For example:
- views
```
-should be in french
+should be in French
```
- vues
```
@@ -57,7 +57,7 @@ For example:
{VAR_PLURAL, plural, =0 {No videos} =1 {1 video} other { videos} }
```
-should be in french
+should be in French
```
{VAR_PLURAL, plural, =0 {Aucune vidéo} =1 {1 vidéo} other { vidéos} }
diff --git a/yarn.lock b/yarn.lock
index f720db1b5..4b8b1abfb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -44,6 +44,17 @@
ajv-draft-04 "^1.0.0"
call-me-maybe "^1.0.2"
+"@asamuzakjp/css-color@^3.2.0":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-3.2.0.tgz#cc42f5b85c593f79f1fa4f25d2b9b321e61d1794"
+ integrity sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==
+ dependencies:
+ "@csstools/css-calc" "^2.1.3"
+ "@csstools/css-color-parser" "^3.0.9"
+ "@csstools/css-parser-algorithms" "^3.0.4"
+ "@csstools/css-tokenizer" "^3.0.3"
+ lru-cache "^10.4.3"
+
"@assemblyscript/loader@^0.19.21":
version "0.19.23"
resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.19.23.tgz#7fccae28d0a2692869f1d1219d36093bc24d5e72"
@@ -679,6 +690,11 @@
dependencies:
"@babel/types" "^7.27.1"
+"@babel/runtime@^7.25.0", "@babel/runtime@^7.26.10", "@babel/runtime@^7.27.6":
+ version "7.27.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.6.tgz#ec4070a04d76bae8ddbb10770ba55714a417b7c6"
+ integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==
+
"@babel/template@^7.27.1":
version "7.27.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d"
@@ -724,6 +740,34 @@
resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-13.1.0.tgz#026e29b04401c92fc4307223fbaadf1ff3e5551e"
integrity sha512-q5P52BYb1hwVWE6dtID7VvuJWrlfbCv4klj7BjUUOqMz4jbSZD4C9fJ9lRjL2jnBGTg+gDDlaXN51rkWcLk4fg==
+"@csstools/color-helpers@^5.0.2":
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.2.tgz#82592c9a7c2b83c293d9161894e2a6471feb97b8"
+ integrity sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==
+
+"@csstools/css-calc@^2.1.3", "@csstools/css-calc@^2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.4.tgz#8473f63e2fcd6e459838dd412401d5948f224c65"
+ integrity sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==
+
+"@csstools/css-color-parser@^3.0.9":
+ version "3.0.10"
+ resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz#79fc68864dd43c3b6782d2b3828bc0fa9d085c10"
+ integrity sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==
+ dependencies:
+ "@csstools/color-helpers" "^5.0.2"
+ "@csstools/css-calc" "^2.1.4"
+
+"@csstools/css-parser-algorithms@^3.0.4":
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076"
+ integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==
+
+"@csstools/css-tokenizer@^3.0.3":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3"
+ integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==
+
"@dabh/diagnostics@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
@@ -747,126 +791,256 @@
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz#830d6476cbbca0c005136af07303646b419f1162"
integrity sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==
+"@esbuild/aix-ppc64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz#164b19122e2ed54f85469df9dea98ddb01d5e79e"
+ integrity sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==
+
"@esbuild/android-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz#d11d4fc299224e729e2190cacadbcc00e7a9fd67"
integrity sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==
+"@esbuild/android-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz#8f539e7def848f764f6432598e51cc3820fde3a5"
+ integrity sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==
+
"@esbuild/android-arm@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.4.tgz#5660bd25080553dd2a28438f2a401a29959bd9b1"
integrity sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==
+"@esbuild/android-arm@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.6.tgz#4ceb0f40113e9861169be83e2a670c260dd234ff"
+ integrity sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==
+
"@esbuild/android-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.4.tgz#18ddde705bf984e8cd9efec54e199ac18bc7bee1"
integrity sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==
+"@esbuild/android-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.6.tgz#ad4f280057622c25fe985c08999443a195dc63a8"
+ integrity sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==
+
"@esbuild/darwin-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz#b0b7fb55db8fc6f5de5a0207ae986eb9c4766e67"
integrity sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==
+"@esbuild/darwin-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz#d1f04027396b3d6afc96bacd0d13167dfd9f01f7"
+ integrity sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==
+
"@esbuild/darwin-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz#e6813fdeba0bba356cb350a4b80543fbe66bf26f"
integrity sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==
+"@esbuild/darwin-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz#2b4a6cedb799f635758d7832d75b23772c8ef68f"
+ integrity sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==
+
"@esbuild/freebsd-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz#dc11a73d3ccdc308567b908b43c6698e850759be"
integrity sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==
+"@esbuild/freebsd-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz#a26266cc97dd78dc3c3f3d6788b1b83697b1055d"
+ integrity sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==
+
"@esbuild/freebsd-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz#91da08db8bd1bff5f31924c57a81dab26e93a143"
integrity sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==
+"@esbuild/freebsd-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz#9feb8e826735c568ebfd94859b22a3fbb6a9bdd2"
+ integrity sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==
+
"@esbuild/linux-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz#efc15e45c945a082708f9a9f73bfa8d4db49728a"
integrity sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==
+"@esbuild/linux-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz#c07cbed8e249f4c28e7f32781d36fc4695293d28"
+ integrity sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==
+
"@esbuild/linux-arm@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz#9b93c3e54ac49a2ede6f906e705d5d906f6db9e8"
integrity sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==
+"@esbuild/linux-arm@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz#d6e2cd8ef3196468065d41f13fa2a61aaa72644a"
+ integrity sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==
+
"@esbuild/linux-ia32@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz#be8ef2c3e1d99fca2d25c416b297d00360623596"
integrity sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==
+"@esbuild/linux-ia32@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz#3e682bd47c4eddcc4b8f1393dfc8222482f17997"
+ integrity sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==
+
"@esbuild/linux-loong64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz#b0840a2707c3fc02eec288d3f9defa3827cd7a87"
integrity sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==
+"@esbuild/linux-loong64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz#473f5ea2e52399c08ad4cd6b12e6dbcddd630f05"
+ integrity sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==
+
"@esbuild/linux-mips64el@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz#2a198e5a458c9f0e75881a4e63d26ba0cf9df39f"
integrity sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==
+"@esbuild/linux-mips64el@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz#9960631c9fd61605b0939c19043acf4ef2b51718"
+ integrity sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==
+
"@esbuild/linux-ppc64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz#64f4ae0b923d7dd72fb860b9b22edb42007cf8f5"
integrity sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==
+"@esbuild/linux-ppc64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz#477cbf8bb04aa034b94f362c32c86b5c31db8d3e"
+ integrity sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==
+
"@esbuild/linux-riscv64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz#fb2844b11fdddd39e29d291c7cf80f99b0d5158d"
integrity sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==
+"@esbuild/linux-riscv64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz#bcdb46c8fb8e93aa779e9a0a62cd4ac00dcac626"
+ integrity sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==
+
"@esbuild/linux-s390x@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz#1466876e0aa3560c7673e63fdebc8278707bc750"
integrity sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==
+"@esbuild/linux-s390x@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz#f412cf5fdf0aea849ff51c73fd817c6c0234d46d"
+ integrity sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==
+
"@esbuild/linux-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz#c10fde899455db7cba5f11b3bccfa0e41bf4d0cd"
integrity sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==
+"@esbuild/linux-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz#d8233c09b5ebc0c855712dc5eeb835a3a3341108"
+ integrity sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==
+
"@esbuild/netbsd-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz#02e483fbcbe3f18f0b02612a941b77be76c111a4"
integrity sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==
+"@esbuild/netbsd-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz#f51ae8dd1474172e73cf9cbaf8a38d1c72dd8f1a"
+ integrity sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==
+
"@esbuild/netbsd-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz#ec401fb0b1ed0ac01d978564c5fc8634ed1dc2ed"
integrity sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==
+"@esbuild/netbsd-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz#a267538602c0e50a858cf41dcfe5d8036f8da8e7"
+ integrity sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==
+
"@esbuild/openbsd-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz#f272c2f41cfea1d91b93d487a51b5c5ca7a8c8c4"
integrity sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==
+"@esbuild/openbsd-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz#a51be60c425b85c216479b8c344ad0511635f2d2"
+ integrity sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==
+
"@esbuild/openbsd-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz#2e25950bc10fa9db1e5c868e3d50c44f7c150fd7"
integrity sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==
+"@esbuild/openbsd-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz#7e4a743c73f75562e29223ba69d0be6c9c9008da"
+ integrity sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==
+
+"@esbuild/openharmony-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz#2087a5028f387879154ebf44bdedfafa17682e5b"
+ integrity sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==
+
"@esbuild/sunos-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz#cd596fa65a67b3b7adc5ecd52d9f5733832e1abd"
integrity sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==
+"@esbuild/sunos-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz#56531f861723ea0dc6283a2bb8837304223cb736"
+ integrity sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==
+
"@esbuild/win32-arm64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz#b4dbcb57b21eeaf8331e424c3999b89d8951dc88"
integrity sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==
+"@esbuild/win32-arm64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz#f4989f033deac6fae323acff58764fa8bc01436e"
+ integrity sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==
+
"@esbuild/win32-ia32@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz#410842e5d66d4ece1757634e297a87635eb82f7a"
integrity sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==
+"@esbuild/win32-ia32@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz#b260e9df71e3939eb33925076d39f63cec7d1525"
+ integrity sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==
+
"@esbuild/win32-x64@0.25.4":
version "0.25.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz#0b17ec8a70b2385827d52314c1253160a0b9bacc"
integrity sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==
+"@esbuild/win32-x64@0.25.6":
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz#4276edd5c105bc28b11c6a1f76fb9d29d1bd25c1"
+ integrity sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==
+
"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a"
@@ -938,6 +1112,54 @@
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==
+"@formatjs/ecma402-abstract@2.3.4":
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz#e90c5a846ba2b33d92bc400fdd709da588280fbc"
+ integrity sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==
+ dependencies:
+ "@formatjs/fast-memoize" "2.2.7"
+ "@formatjs/intl-localematcher" "0.6.1"
+ decimal.js "^10.4.3"
+ tslib "^2.8.0"
+
+"@formatjs/fast-memoize@2.2.7":
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz#707f9ddaeb522a32f6715bb7950b0831f4cc7b15"
+ integrity sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==
+ dependencies:
+ tslib "^2.8.0"
+
+"@formatjs/icu-messageformat-parser@2.11.2":
+ version "2.11.2"
+ resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz#85aea211bea40aa81ee1d44ac7accc3cf5500a73"
+ integrity sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==
+ dependencies:
+ "@formatjs/ecma402-abstract" "2.3.4"
+ "@formatjs/icu-skeleton-parser" "1.8.14"
+ tslib "^2.8.0"
+
+"@formatjs/icu-skeleton-parser@1.8.14":
+ version "1.8.14"
+ resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz#b9581d00363908efb29817fdffc32b79f41dabe5"
+ integrity sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==
+ dependencies:
+ "@formatjs/ecma402-abstract" "2.3.4"
+ tslib "^2.8.0"
+
+"@formatjs/intl-localematcher@0.6.1":
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz#25dc30675320bf65a9d7f73876fc1e4064c0e299"
+ integrity sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==
+ dependencies:
+ tslib "^2.8.0"
+
+"@gulpjs/to-absolute-glob@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz#1fc2460d3953e1d9b9f2dfdb4bcc99da4710c021"
+ integrity sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==
+ dependencies:
+ is-negated-glob "^1.0.0"
+
"@hapi/boom@^10.0.0":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685"
@@ -2949,11 +3171,21 @@
"@types/methods" "^1.1.4"
"@types/superagent" "^8.1.0"
+"@types/symlink-or-copy@^1.2.0":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d"
+ integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==
+
"@types/triple-beam@^1.3.2":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c"
integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==
+"@types/trusted-types@^2.0.7":
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
+ integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
+
"@types/tv4@*":
version "1.2.33"
resolved "https://registry.yarnpkg.com/@types/tv4/-/tv4-1.2.33.tgz#f6ac0f85cabffde144a16bf7ef8c043e89d1854a"
@@ -3185,7 +3417,7 @@ addr-to-ip-port@^2.0.0:
resolved "https://registry.yarnpkg.com/addr-to-ip-port/-/addr-to-ip-port-2.0.0.tgz#ab383c140392f3e99d5e9c34b88c259fa35274b1"
integrity sha512-9bYbtjamtdLHZSqVIUXhilOryNPiL+x+Q5J/Unpg4VY3ZIkK3fT52UoErj1NdUeVm3J1t2iBEAur4Ywbl/bahw==
-addressparser@^1.0.1:
+addressparser@1.0.1, addressparser@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746"
integrity sha512-aQX7AISOMM7HFE0iZ3+YnD07oIeJqWGVnJ+ZIKaBZAk03ftmVYVqsGas/rbXKR21n4D/hKCSHypvcyOkds/xzg==
@@ -3197,6 +3429,11 @@ agent-base@6:
dependencies:
debug "4"
+agent-base@^7.1.0, agent-base@^7.1.2:
+ version "7.1.4"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8"
+ integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==
+
ajv-draft-04@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8"
@@ -3274,6 +3511,14 @@ any-base@^1.1.0:
resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe"
integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==
+anymatch@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
append-field@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
@@ -3766,6 +4011,15 @@ bl@^4.0.3:
inherits "^2.0.4"
readable-stream "^3.4.0"
+bl@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273"
+ integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==
+ dependencies:
+ buffer "^6.0.3"
+ inherits "^2.0.4"
+ readable-stream "^3.4.0"
+
block-iterator@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/block-iterator/-/block-iterator-1.1.1.tgz#3c8a94e083febf8da59d8baad1006ffee1a74694"
@@ -3851,6 +4105,38 @@ braces@^3.0.3:
dependencies:
fill-range "^7.1.1"
+broccoli-node-api@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz#391aa6edecd2a42c63c111b4162956b2fa288cb6"
+ integrity sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==
+
+broccoli-node-info@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz#feb01c13020792f429e01d7f7845dc5b3a7932b3"
+ integrity sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==
+
+broccoli-output-wrapper@^3.2.5:
+ version "3.2.5"
+ resolved "https://registry.yarnpkg.com/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz#514b17801c92922a2c2f87fd145df2a25a11bc5f"
+ integrity sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw==
+ dependencies:
+ fs-extra "^8.1.0"
+ heimdalljs-logger "^0.1.10"
+ symlink-or-copy "^1.2.0"
+
+broccoli-plugin@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz#dd176a85efe915ed557d913744b181abe05047db"
+ integrity sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg==
+ dependencies:
+ broccoli-node-api "^1.7.0"
+ broccoli-output-wrapper "^3.2.5"
+ fs-merger "^3.2.1"
+ promise-map-series "^0.3.0"
+ quick-temp "^0.1.8"
+ rimraf "^3.0.2"
+ symlink-or-copy "^1.3.1"
+
browser-stdout@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
@@ -4139,6 +4425,23 @@ cheerio@1.0.0-rc.12:
parse5 "^7.0.0"
parse5-htmlparser2-tree-adapter "^7.0.0"
+cheerio@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.1.0.tgz#87b9bec6dd3696e405ea79da7d2749d8308b0953"
+ integrity sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==
+ dependencies:
+ cheerio-select "^2.1.0"
+ dom-serializer "^2.0.0"
+ domhandler "^5.0.3"
+ domutils "^3.2.2"
+ encoding-sniffer "^0.2.0"
+ htmlparser2 "^10.0.0"
+ parse5 "^7.3.0"
+ parse5-htmlparser2-tree-adapter "^7.1.0"
+ parse5-parser-stream "^7.1.2"
+ undici "^7.10.0"
+ whatwg-mimetype "^4.0.0"
+
chokidar@^4.0.1, chokidar@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30"
@@ -4231,6 +4534,11 @@ cliui@^8.0.1:
strip-ansi "^6.0.1"
wrap-ansi "^7.0.0"
+clone@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
+ integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
+
cluster-key-slot@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac"
@@ -4286,6 +4594,11 @@ colors@1.0.x:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==
+colors@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
+ integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
+
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
@@ -4306,6 +4619,11 @@ commander@11.0.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67"
integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==
+commander@^12.1.0:
+ version "12.1.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
+ integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
+
commander@^13.1.0:
version "13.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46"
@@ -4349,6 +4667,26 @@ compress-commons@^6.0.2:
normalize-path "^3.0.0"
readable-stream "^4.0.0"
+compressible@~2.0.18:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+compression@^1.7.4:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79"
+ integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==
+ dependencies:
+ bytes "3.1.2"
+ compressible "~2.0.18"
+ debug "2.6.9"
+ negotiator "~0.6.4"
+ on-headers "~1.1.0"
+ safe-buffer "5.2.1"
+ vary "~1.1.2"
+
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -4416,6 +4754,11 @@ content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+
cookie-parser@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.7.tgz#e2125635dfd766888ffe90d60c286404fa0e7b26"
@@ -4570,6 +4913,14 @@ css-what@^6.1.0:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+cssstyle@^4.0.1:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.6.0.tgz#ea18007024e3167f4f105315f3ec2d982bf48ed9"
+ integrity sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==
+ dependencies:
+ "@asamuzakjp/css-color" "^3.2.0"
+ rrweb-cssom "^0.8.0"
+
cycle@1.0.x:
version "1.0.3"
resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
@@ -4595,6 +4946,14 @@ data-uri-to-buffer@^4.0.0:
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
+data-urls@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde"
+ integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==
+ dependencies:
+ whatwg-mimetype "^4.0.0"
+ whatwg-url "^14.0.0"
+
data-view-buffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570"
@@ -4627,7 +4986,7 @@ dateformat@^4.6.3:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
-debug@2.6.9:
+debug@2.6.9, debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -4665,6 +5024,11 @@ decamelize@^4.0.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
+decimal.js@^10.4.3:
+ version "10.6.0"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a"
+ integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==
+
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
@@ -4903,6 +5267,13 @@ domhandler@^5.0.2, domhandler@^5.0.3:
dependencies:
domelementtype "^2.3.0"
+dompurify@^3.1.6:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.6.tgz#ca040a6ad2b88e2a92dc45f38c79f84a714a1cad"
+ integrity sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==
+ optionalDependencies:
+ "@types/trusted-types" "^2.0.7"
+
domutils@^2.4.2:
version "2.8.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
@@ -4912,7 +5283,7 @@ domutils@^2.4.2:
domelementtype "^2.2.0"
domhandler "^4.2.0"
-domutils@^3.0.1:
+domutils@^3.0.1, domutils@^3.2.1, domutils@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78"
integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
@@ -5020,6 +5391,14 @@ encoding-japanese@2.2.0:
resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-2.2.0.tgz#0ef2d2351250547f432a2dd155453555c16deb59"
integrity sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==
+encoding-sniffer@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz#396ec97ac22ce5a037ba44af1992ac9d46a7b819"
+ integrity sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==
+ dependencies:
+ iconv-lite "^0.6.3"
+ whatwg-encoding "^3.1.1"
+
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -5066,6 +5445,11 @@ enhanced-resolve@^5.17.1:
graceful-fs "^4.2.4"
tapable "^2.2.0"
+ensure-posix-path@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce"
+ integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==
+
entities@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
@@ -5081,6 +5465,11 @@ entities@^6.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.0.tgz#09c9e29cb79b0a6459a9b9db9efb418ac5bb8e51"
integrity sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==
+eol@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd"
+ integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==
+
err-code@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920"
@@ -5245,6 +5634,38 @@ es6-weak-map@^2.0.3:
es6-iterator "^2.0.3"
es6-symbol "^3.1.1"
+esbuild@^0.25.0:
+ version "0.25.6"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.6.tgz#9b82a3db2fa131aec069ab040fd57ed0a880cdcd"
+ integrity sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==
+ optionalDependencies:
+ "@esbuild/aix-ppc64" "0.25.6"
+ "@esbuild/android-arm" "0.25.6"
+ "@esbuild/android-arm64" "0.25.6"
+ "@esbuild/android-x64" "0.25.6"
+ "@esbuild/darwin-arm64" "0.25.6"
+ "@esbuild/darwin-x64" "0.25.6"
+ "@esbuild/freebsd-arm64" "0.25.6"
+ "@esbuild/freebsd-x64" "0.25.6"
+ "@esbuild/linux-arm" "0.25.6"
+ "@esbuild/linux-arm64" "0.25.6"
+ "@esbuild/linux-ia32" "0.25.6"
+ "@esbuild/linux-loong64" "0.25.6"
+ "@esbuild/linux-mips64el" "0.25.6"
+ "@esbuild/linux-ppc64" "0.25.6"
+ "@esbuild/linux-riscv64" "0.25.6"
+ "@esbuild/linux-s390x" "0.25.6"
+ "@esbuild/linux-x64" "0.25.6"
+ "@esbuild/netbsd-arm64" "0.25.6"
+ "@esbuild/netbsd-x64" "0.25.6"
+ "@esbuild/openbsd-arm64" "0.25.6"
+ "@esbuild/openbsd-x64" "0.25.6"
+ "@esbuild/openharmony-arm64" "0.25.6"
+ "@esbuild/sunos-x64" "0.25.6"
+ "@esbuild/win32-arm64" "0.25.6"
+ "@esbuild/win32-ia32" "0.25.6"
+ "@esbuild/win32-x64" "0.25.6"
+
esbuild@^0.25.4, esbuild@~0.25.0:
version "0.25.4"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.4.tgz#bb9a16334d4ef2c33c7301a924b8b863351a0854"
@@ -5657,7 +6078,7 @@ express-validator@^7.0.1:
lodash "^4.17.21"
validator "~13.12.0"
-express@^4.18.1, express@^4.21.1:
+express@^4.18.1, express@^4.21.1, express@^4.21.2:
version "4.21.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32"
integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==
@@ -5835,7 +6256,7 @@ fast-xml-parser@^5.2.2:
dependencies:
strnum "^2.1.0"
-fastq@^1.6.0:
+fastq@^1.13.0, fastq@^1.6.0:
version "1.19.1"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5"
integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==
@@ -6087,7 +6508,7 @@ fs-constants@^1.0.0:
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
-fs-extra@^11.1.0:
+fs-extra@^11.1.0, fs-extra@^11.2.0:
version "11.3.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d"
integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==
@@ -6096,6 +6517,26 @@ fs-extra@^11.1.0:
jsonfile "^6.0.1"
universalify "^2.0.0"
+fs-extra@^8.0.1, fs-extra@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+ integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-merger@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/fs-merger/-/fs-merger-3.2.1.tgz#a225b11ae530426138294b8fbb19e82e3d4e0b3b"
+ integrity sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug==
+ dependencies:
+ broccoli-node-api "^1.7.0"
+ broccoli-node-info "^2.1.0"
+ fs-extra "^8.0.1"
+ fs-tree-diff "^2.0.1"
+ walk-sync "^2.2.0"
+
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -6103,6 +6544,14 @@ fs-minipass@^2.0.0:
dependencies:
minipass "^3.0.0"
+fs-mkdirp-stream@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz#1e82575c4023929ad35cf69269f84f1a8c973aa7"
+ integrity sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==
+ dependencies:
+ graceful-fs "^4.2.8"
+ streamx "^2.12.0"
+
fs-native-extensions@^1.3.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/fs-native-extensions/-/fs-native-extensions-1.4.2.tgz#13b015e7a30e9555f68f504b57daef36d896ba73"
@@ -6111,6 +6560,17 @@ fs-native-extensions@^1.3.1:
require-addon "^1.1.0"
which-runtime "^1.2.0"
+fs-tree-diff@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa"
+ integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==
+ dependencies:
+ "@types/symlink-or-copy" "^1.2.0"
+ heimdalljs-logger "^0.1.7"
+ object-assign "^4.1.0"
+ path-posix "^1.0.0"
+ symlink-or-copy "^1.1.8"
+
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -6279,6 +6739,20 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
+glob-stream@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-8.0.3.tgz#87e63153aadf05bd0207cde1a253ee39d91458b9"
+ integrity sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==
+ dependencies:
+ "@gulpjs/to-absolute-glob" "^4.0.0"
+ anymatch "^3.1.3"
+ fastq "^1.13.0"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ is-negated-glob "^1.0.0"
+ normalize-path "^3.0.0"
+ streamx "^2.12.5"
+
glob@7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
@@ -6396,7 +6870,7 @@ got@^14.4.5:
responselike "^3.0.0"
type-fest "^4.26.1"
-graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.8:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -6406,6 +6880,25 @@ graphemer@^1.4.0:
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
+gulp-sort@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/gulp-sort/-/gulp-sort-2.0.0.tgz#c6762a2f1f0de0a3fc595a21599d3fac8dba1aca"
+ integrity sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==
+ dependencies:
+ through2 "^2.0.1"
+
+handlebars@^4.7.8:
+ version "4.7.8"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9"
+ integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==
+ dependencies:
+ minimist "^1.2.5"
+ neo-async "^2.6.2"
+ source-map "^0.6.1"
+ wordwrap "^1.0.0"
+ optionalDependencies:
+ uglify-js "^3.1.4"
+
has-async-hooks@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-async-hooks/-/has-async-hooks-1.0.0.tgz#3df965ade8cd2d9dbfdacfbca3e0a5152baaf204"
@@ -6483,6 +6976,21 @@ he@1.2.0, he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+heimdalljs-logger@^0.1.10, heimdalljs-logger@^0.1.7:
+ version "0.1.10"
+ resolved "https://registry.yarnpkg.com/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz#90cad58aabb1590a3c7e640ddc6a4cd3a43faaf7"
+ integrity sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g==
+ dependencies:
+ debug "^2.2.0"
+ heimdalljs "^0.2.6"
+
+heimdalljs@^0.2.6:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/heimdalljs/-/heimdalljs-0.2.6.tgz#b0eebabc412813aeb9542f9cc622cb58dbdcd9fe"
+ integrity sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==
+ dependencies:
+ rsvp "~3.2.1"
+
helmet@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/helmet/-/helmet-8.1.0.tgz#f96d23fedc89e9476ecb5198181009c804b8b38c"
@@ -6505,6 +7013,13 @@ homedir-polyfill@^1.0.1:
dependencies:
parse-passwd "^1.0.0"
+html-encoding-sniffer@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448"
+ integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==
+ dependencies:
+ whatwg-encoding "^3.1.1"
+
html-to-text@9.0.5, html-to-text@^9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-9.0.5.tgz#6149a0f618ae7a0db8085dca9bbf96d32bb8368d"
@@ -6516,6 +7031,16 @@ html-to-text@9.0.5, html-to-text@^9.0.5:
htmlparser2 "^8.0.2"
selderee "^0.11.0"
+htmlparser2@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.0.0.tgz#77ad249037b66bf8cc99c6e286ef73b83aeb621d"
+ integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+ domutils "^3.2.1"
+ entities "^6.0.0"
+
htmlparser2@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-5.0.1.tgz#7daa6fc3e35d6107ac95a4fc08781f091664f6e7"
@@ -6578,6 +7103,14 @@ http-problem-details@^0.1.5:
resolved "https://registry.yarnpkg.com/http-problem-details/-/http-problem-details-0.1.7.tgz#223fda43d8ff7cc6634a592d4706b2c99e0be46d"
integrity sha512-+ccES43ePQOnZDIkEuo4gNyT0R/Gkulk79oZ3a9FuQQFZYPcUx0OPBe5ztmehe6t79WN/me7APHX3yD6Ha5CHA==
+http-proxy-agent@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
+ integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==
+ dependencies:
+ agent-base "^7.1.0"
+ debug "^4.3.4"
+
http2-express@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/http2-express/-/http2-express-1.0.1.tgz#5865adc1637220eec55a6dafa2c8d495607751e8"
@@ -6599,6 +7132,14 @@ https-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
+https-proxy-agent@^7.0.5:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9"
+ integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==
+ dependencies:
+ agent-base "^7.1.2"
+ debug "4"
+
human-signals@^4.3.0:
version "4.3.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
@@ -6637,6 +7178,48 @@ i18n@^0.15.0:
math-interval-parser "^2.0.1"
mustache "^4.2.0"
+i18next-icu@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/i18next-icu/-/i18next-icu-2.3.0.tgz#eee6a15ef4c0639d5878aec4db6ec692eaed32bd"
+ integrity sha512-x+j7kd5nDJCfbU53uwsMfXD7ALPu5uv0bqjAMQ5nVvXRoj1L7gkmswKtM3XDWYo4YUHf1jznlhSdPyy0xEwU+Q==
+
+i18next-parser@^9.3.0:
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.3.0.tgz#65c226cac54cd2783b59715a366be1e3515dd8e6"
+ integrity sha512-VaQqk/6nLzTFx1MDiCZFtzZXKKyBV6Dv0cJMFM/hOt4/BWHWRgYafzYfVQRUzotwUwjqeNCprWnutzD/YAGczg==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ broccoli-plugin "^4.0.7"
+ cheerio "^1.0.0"
+ colors "^1.4.0"
+ commander "^12.1.0"
+ eol "^0.9.1"
+ esbuild "^0.25.0"
+ fs-extra "^11.2.0"
+ gulp-sort "^2.0.0"
+ i18next "^23.5.1 || ^24.2.0"
+ js-yaml "^4.1.0"
+ lilconfig "^3.1.3"
+ rsvp "^4.8.5"
+ sort-keys "^5.0.0"
+ typescript "^5.0.4"
+ vinyl "^3.0.0"
+ vinyl-fs "^4.0.0"
+
+"i18next@^23.5.1 || ^24.2.0":
+ version "24.2.3"
+ resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.2.3.tgz#3a05f72615cbd7c00d7e348667e2aabef1df753b"
+ integrity sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==
+ dependencies:
+ "@babel/runtime" "^7.26.10"
+
+i18next@^25.3.2:
+ version "25.3.2"
+ resolved "https://registry.yarnpkg.com/i18next/-/i18next-25.3.2.tgz#3d6a7d1dc058caa1b9bdca47fd585483e2e7a637"
+ integrity sha512-JSnbZDxRVbphc5jiptxr3o2zocy5dEqpVm9qCGdJwRNO+9saUJS0/u4LnM/13C23fUEWxAylPqKU/NpMV/IjqA==
+ dependencies:
+ "@babel/runtime" "^7.27.6"
+
iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -6644,6 +7227,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
+iconv-lite@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.0.tgz#59cdde0a2a297cc2aeb0c6445a195ee89f127550"
+ integrity sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
iconv-lite@0.6.3, iconv-lite@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -6750,6 +7340,16 @@ internal-slot@^1.1.0:
hasown "^2.0.2"
side-channel "^1.1.0"
+intl-messageformat@^10.7.16:
+ version "10.7.16"
+ resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.16.tgz#d909f9f9f4ab857fbe681d559b958dd4dd9f665a"
+ integrity sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==
+ dependencies:
+ "@formatjs/ecma402-abstract" "2.3.4"
+ "@formatjs/fast-memoize" "2.2.7"
+ "@formatjs/icu-messageformat-parser" "2.11.2"
+ tslib "^2.8.0"
+
ioredis@^5.2.3, ioredis@^5.4.1:
version "5.6.1"
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.6.1.tgz#1ed7dc9131081e77342503425afceaf7357ae599"
@@ -6941,6 +7541,11 @@ is-map@^2.0.3:
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
+is-negated-glob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2"
+ integrity sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==
+
is-number-object@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541"
@@ -6959,7 +7564,7 @@ is-plain-obj@^2.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
-is-plain-obj@^4.1.0:
+is-plain-obj@^4.0.0, is-plain-obj@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0"
integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==
@@ -6969,6 +7574,11 @@ is-plain-object@^5.0.0:
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
+
is-promise@^2.0.0, is-promise@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
@@ -7060,6 +7670,11 @@ is-unicode-supported@^2.0.0:
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a"
integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==
+is-valid-glob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa"
+ integrity sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==
+
is-weakmap@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd"
@@ -7205,6 +7820,33 @@ jsbn@~0.1.0:
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
+jsdom@^24.1.1:
+ version "24.1.3"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-24.1.3.tgz#88e4a07cb9dd21067514a619e9f17b090a394a9f"
+ integrity sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==
+ dependencies:
+ cssstyle "^4.0.1"
+ data-urls "^5.0.0"
+ decimal.js "^10.4.3"
+ form-data "^4.0.0"
+ html-encoding-sniffer "^4.0.0"
+ http-proxy-agent "^7.0.2"
+ https-proxy-agent "^7.0.5"
+ is-potential-custom-element-name "^1.0.1"
+ nwsapi "^2.2.12"
+ parse5 "^7.1.2"
+ rrweb-cssom "^0.7.1"
+ saxes "^6.0.0"
+ symbol-tree "^3.2.4"
+ tough-cookie "^4.1.4"
+ w3c-xmlserializer "^5.0.0"
+ webidl-conversions "^7.0.0"
+ whatwg-encoding "^3.1.1"
+ whatwg-mimetype "^4.0.0"
+ whatwg-url "^14.0.0"
+ ws "^8.18.0"
+ xml-name-validator "^5.0.0"
+
jsesc@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
@@ -7252,6 +7894,13 @@ json5@^2.2.3:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
@@ -7421,6 +8070,11 @@ leac@^0.6.0:
resolved "https://registry.yarnpkg.com/leac/-/leac-0.6.0.tgz#dcf136e382e666bd2475f44a1096061b70dc0912"
integrity sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==
+lead@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/lead/-/lead-4.0.0.tgz#5317a49effb0e7ec3a0c8fb9c1b24fb716aab939"
+ integrity sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==
+
leven@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -7461,6 +8115,11 @@ lie@~3.3.0:
dependencies:
immediate "~3.0.5"
+lilconfig@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4"
+ integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==
+
limiter@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2"
@@ -7628,7 +8287,7 @@ lowercase-keys@^3.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2"
integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==
-lru-cache@^10.2.0:
+lru-cache@^10.2.0, lru-cache@^10.4.3:
version "10.4.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
@@ -7688,6 +8347,27 @@ magnet-uri@^7.0.5, magnet-uri@^7.0.7:
bep53-range "^2.0.0"
uint8-util "^2.2.5"
+maildev@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/maildev/-/maildev-2.2.1.tgz#0a7ea8188bc6d9fea6bd08dbc63ecf4872acc67c"
+ integrity sha512-uNSJ4LpiNfCMw5KpWAM5x1UgOyG3ngeNwzBqw4/Wl18ECkJDyXBYpTH44HCG8LqAOFLkUiLl/1Ah5lrQhv3GzQ==
+ dependencies:
+ addressparser "1.0.1"
+ async "^3.2.3"
+ commander "^12.1.0"
+ compression "^1.7.4"
+ cors "^2.8.5"
+ dompurify "^3.1.6"
+ express "^4.21.2"
+ iconv-lite "0.5.0"
+ jsdom "^24.1.1"
+ mime "2.4.4"
+ nodemailer "^6.9.14"
+ smtp-server "^3.13.4"
+ socket.io "^4.7.5"
+ uue "3.1.2"
+ wildstring "1.0.9"
+
mailparser-mit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mailparser-mit/-/mailparser-mit-1.0.0.tgz#19df8436c2a02e1d34a03ec518a2eb065e0a94a4"
@@ -7762,6 +8442,14 @@ markdown-it@^14.0.0:
punycode.js "^2.3.1"
uc.micro "^2.1.0"
+matcher-collection@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29"
+ integrity sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==
+ dependencies:
+ "@types/minimatch" "^3.0.3"
+ minimatch "^3.0.2"
+
math-interval-parser@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-2.0.1.tgz#e22cd6d15a0a7f4c03aec560db76513da615bed4"
@@ -7859,7 +8547,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-mime-db@^1.54.0:
+"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0:
version "1.54.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
@@ -7883,6 +8571,11 @@ mime@1.6.0, mime@^1.3.4, mime@^1.6.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+mime@2.4.4:
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
+ integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
+
mime@2.6.0, mime@^2.4.6:
version "2.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
@@ -7915,7 +8608,7 @@ min-document@^2.19.0:
dependencies:
dom-walk "^0.1.0"
-minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
+minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -7943,7 +8636,7 @@ minimatch@^9.0.4, minimatch@^9.0.5:
dependencies:
brace-expansion "^2.0.1"
-minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6, minimist@^1.2.8:
+minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -7995,6 +8688,11 @@ mkdirp@^2.1.6:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19"
integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==
+mktemp@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b"
+ integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A==
+
mmdb-lib@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/mmdb-lib/-/mmdb-lib-2.2.0.tgz#fbb08116e56d7b7874314dc680bb74693e5026ff"
@@ -8178,6 +8876,16 @@ negotiator@^1.0.0:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a"
integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
+negotiator@~0.6.4:
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
+ integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
netmask@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7"
@@ -8299,16 +9007,16 @@ nodemailer@6.9.16:
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.16.tgz#3ebdf6c6f477c571c0facb0727b33892635e0b8b"
integrity sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==
+nodemailer@7.0.3, nodemailer@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-7.0.3.tgz#c098ce79ac60c7c111a86949eed2f99bd00cdac3"
+ integrity sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==
+
nodemailer@^6.9.13, nodemailer@^6.9.14:
version "6.10.1"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.10.1.tgz#cbc434c54238f83a51c07eabd04e2b3e832da623"
integrity sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==
-nodemailer@^7.0.3:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-7.0.3.tgz#c098ce79ac60c7c111a86949eed2f99bd00cdac3"
- integrity sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==
-
nopt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
@@ -8316,7 +9024,7 @@ nopt@^5.0.0:
dependencies:
abbrev "1"
-normalize-path@^3.0.0:
+normalize-path@3.0.0, normalize-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
@@ -8326,6 +9034,13 @@ normalize-url@^8.0.1:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a"
integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==
+now-and-later@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-3.0.0.tgz#cdc045dc5b894b35793cf276cc3206077bb7302d"
+ integrity sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==
+ dependencies:
+ once "^1.4.0"
+
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -8365,7 +9080,12 @@ nth-check@^2.0.1:
dependencies:
boolbase "^1.0.0"
-object-assign@^4, object-assign@^4.1.1:
+nwsapi@^2.2.12:
+ version "2.2.20"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.20.tgz#22e53253c61e7b0e7e93cef42c891154bcca11ef"
+ integrity sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==
+
+object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
@@ -8450,6 +9170,11 @@ on-headers@~1.0.2:
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+on-headers@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65"
+ integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==
+
on-net-listen@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/on-net-listen/-/on-net-listen-1.1.2.tgz#671e55a81c910fa7e5b1e4d506545e9ea0f2e11c"
@@ -8680,7 +9405,7 @@ parse-torrent@^11.0.14, parse-torrent@^11.0.18:
queue-microtask "^1.2.3"
uint8-util "^2.2.5"
-parse5-htmlparser2-tree-adapter@^7.0.0:
+parse5-htmlparser2-tree-adapter@^7.0.0, parse5-htmlparser2-tree-adapter@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz#b5a806548ed893a43e24ccb42fbb78069311e81b"
integrity sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==
@@ -8688,7 +9413,14 @@ parse5-htmlparser2-tree-adapter@^7.0.0:
domhandler "^5.0.3"
parse5 "^7.0.0"
-parse5@^7.0.0:
+parse5-parser-stream@^7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz#d7c20eadc37968d272e2c02660fff92dd27e60e1"
+ integrity sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==
+ dependencies:
+ parse5 "^7.0.0"
+
+parse5@^7.0.0, parse5@^7.1.2, parse5@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05"
integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==
@@ -8743,6 +9475,11 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+path-posix@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f"
+ integrity sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==
+
path-scurry@^1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
@@ -8888,7 +9625,7 @@ picocolors@^1.1.1:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
-picomatch@^2.2.1, picomatch@^2.3.1:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -9091,6 +9828,11 @@ progress@^2.0.3:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+promise-map-series@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/promise-map-series/-/promise-map-series-0.3.0.tgz#41873ca3652bb7a042b387d538552da9b576f8a1"
+ integrity sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==
+
promise@^7.0.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
@@ -9133,6 +9875,13 @@ ps-tree@^1.2.0:
dependencies:
event-stream "=3.3.4"
+psl@^1.1.33:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6"
+ integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==
+ dependencies:
+ punycode "^2.3.1"
+
pug-attrs@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41"
@@ -9266,7 +10015,7 @@ punycode.js@2.3.1, punycode.js@^2.3.1:
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
-punycode@^2.1.0, punycode@^2.1.1:
+punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
@@ -9285,6 +10034,11 @@ qs@^6.11.0, qs@^6.14.0:
dependencies:
side-channel "^1.1.0"
+querystringify@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
+ integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
+
queue-microtask@^1.2.2, queue-microtask@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -9300,6 +10054,15 @@ quick-lru@^5.1.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+quick-temp@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408"
+ integrity sha512-YsmIFfD9j2zaFwJkzI6eMG7y0lQP7YeWzgtFgNl38pGWZBSXJooZbOWwkcRot7Vt0Fg9L23pX0tqWU3VvLDsiA==
+ dependencies:
+ mktemp "~0.4.0"
+ rimraf "^2.5.4"
+ underscore.string "~3.3.4"
+
railroad-diagrams@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
@@ -9549,6 +10312,16 @@ reinterval@^1.1.0:
resolved "https://registry.yarnpkg.com/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7"
integrity sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==
+remove-trailing-separator@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+ integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==
+
+replace-ext@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-2.0.0.tgz#9471c213d22e1bcc26717cd6e50881d88f812b06"
+ integrity sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==
+
require-addon@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/require-addon/-/require-addon-1.1.0.tgz#0a1ef0ba98b186a3aa304a1abda5208902e63e17"
@@ -9586,6 +10359,11 @@ require-package-name@^2.0.1:
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
integrity sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==
+requires-port@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+
resolve-alpn@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
@@ -9609,6 +10387,13 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+resolve-options@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-2.0.0.tgz#a1a57a9949db549dd075de3f5550675f02f1e4c5"
+ integrity sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==
+ dependencies:
+ value-or-function "^4.0.0"
+
resolve-pkg-maps@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
@@ -9655,6 +10440,13 @@ revalidator@0.1.x:
resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b"
integrity sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==
+rimraf@^2.5.4:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -9711,6 +10503,26 @@ router@^2.2.0:
parseurl "^1.3.3"
path-to-regexp "^8.0.0"
+rrweb-cssom@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz#c73451a484b86dd7cfb1e0b2898df4b703183e4b"
+ integrity sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==
+
+rrweb-cssom@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2"
+ integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==
+
+rsvp@^4.8.5:
+ version "4.8.5"
+ resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
+ integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
+
+rsvp@~3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a"
+ integrity sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==
+
run-applescript@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-3.2.0.tgz#73fb34ce85d3de8076d511ea767c30d4fdfc918b"
@@ -9814,6 +10626,13 @@ sax@>=0.6.0, sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
+saxes@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5"
+ integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==
+ dependencies:
+ xmlchars "^2.2.0"
+
selderee@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.11.0.tgz#6af0c7983e073ad3e35787ffe20cefd9daf0ec8a"
@@ -10117,6 +10936,16 @@ smart-buffer@^4.2.0:
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
+smtp-server@^3.13.4:
+ version "3.14.0"
+ resolved "https://registry.yarnpkg.com/smtp-server/-/smtp-server-3.14.0.tgz#2c2c9078d027fbd8d10c75f2bc62f2217fbf161a"
+ integrity sha512-cEw/hdIY+xw1pkbQbQ23hvnm9kNABAsgYB+jJYGkzAynZxJ2VB9aqC6JhB1vpdDnqan7C7AL3qHYRGwz5eD6BQ==
+ dependencies:
+ base32.js "0.1.0"
+ ipv6-normalize "1.0.1"
+ nodemailer "7.0.3"
+ punycode.js "2.3.1"
+
smtp-server@^3.9.0:
version "3.13.6"
resolved "https://registry.yarnpkg.com/smtp-server/-/smtp-server-3.13.6.tgz#779aa22fd3746bb8b94d25ab78447b6e4b7d5b78"
@@ -10153,7 +10982,7 @@ socket.io-parser@~4.2.4:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
-socket.io@^4.5.4:
+socket.io@^4.5.4, socket.io@^4.7.5:
version "4.8.1"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.1.tgz#fa0eaff965cc97fdf4245e8d4794618459f7558a"
integrity sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==
@@ -10174,11 +11003,23 @@ socks@^2.8.3:
ip-address "^9.0.5"
smart-buffer "^4.2.0"
+sort-keys@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.1.0.tgz#50a3f3d1ad3c5a76d043e0aeeba7299241e9aa5c"
+ integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==
+ dependencies:
+ is-plain-obj "^4.0.0"
+
source-map-js@^1.2.0, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
+source-map@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
speed-limiter@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/speed-limiter/-/speed-limiter-1.0.2.tgz#e4632f476a1d25d32557aad7bd089b3a0d948116"
@@ -10213,7 +11054,7 @@ split@^1.0.1:
dependencies:
through "2"
-sprintf-js@^1.1.3:
+sprintf-js@^1.1.1, sprintf-js@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
@@ -10293,6 +11134,13 @@ stream-combiner@~0.0.4:
dependencies:
duplexer "~0.1.1"
+stream-composer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/stream-composer/-/stream-composer-1.0.2.tgz#7ee61ca1587bf5f31b2e29aa2093cbf11442d152"
+ integrity sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==
+ dependencies:
+ streamx "^2.13.2"
+
stream-shift@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b"
@@ -10325,6 +11173,16 @@ streamx@2.22.0, streamx@^2.10.3, streamx@^2.15.0, streamx@^2.15.1, streamx@^2.17
optionalDependencies:
bare-events "^2.2.0"
+streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0:
+ version "2.22.1"
+ resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.1.tgz#c97cbb0ce18da4f4db5a971dc9ab68ff5dc7f5a5"
+ integrity sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==
+ dependencies:
+ fast-fifo "^1.3.2"
+ text-decoder "^1.1.0"
+ optionalDependencies:
+ bare-events "^2.2.0"
+
string-argv@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
@@ -10546,6 +11404,16 @@ swagger-cli@^4.0.2:
dependencies:
"@apidevtools/swagger-cli" "4.0.4"
+symbol-tree@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
+symlink-or-copy@^1.1.8, symlink-or-copy@^1.2.0, symlink-or-copy@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz#9506dd64d8e98fa21dcbf4018d1eab23e77f71fe"
+ integrity sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA==
+
tapable@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
@@ -10593,6 +11461,13 @@ tar@^6.1.11:
mkdirp "^1.0.3"
yallist "^4.0.0"
+teex@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/teex/-/teex-1.0.1.tgz#b8fa7245ef8e8effa8078281946c85ab780a0b12"
+ integrity sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==
+ dependencies:
+ streamx "^2.12.5"
+
text-decoder@^1.1.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65"
@@ -10630,7 +11505,7 @@ through2@^1.0.0:
readable-stream ">=1.1.13-1 <1.2.0-0"
xtend ">=4.0.0 <4.1.0-0"
-through2@^2.0.3:
+through2@^2.0.1, through2@^2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
@@ -10708,6 +11583,13 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
+to-through@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/to-through/-/to-through-3.0.0.tgz#bf4956eaca5a0476474850a53672bed6906ace54"
+ integrity sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==
+ dependencies:
+ streamx "^2.12.5"
+
to-utf-8@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/to-utf-8/-/to-utf-8-1.3.0.tgz#b2af7be9e003f4c3817cc116d3baed2a054993c9"
@@ -10760,6 +11642,23 @@ torrent-piece@^3.0.1:
dependencies:
uint8-util "^2.1.9"
+tough-cookie@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36"
+ integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==
+ dependencies:
+ psl "^1.1.33"
+ punycode "^2.1.1"
+ universalify "^0.2.0"
+ url-parse "^1.5.3"
+
+tr46@^5.1.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca"
+ integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==
+ dependencies:
+ punycode "^2.3.1"
+
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -10800,7 +11699,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2:
+tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -10930,7 +11829,7 @@ typescript-eslint@^8.26.0:
"@typescript-eslint/parser" "8.32.0"
"@typescript-eslint/utils" "8.32.0"
-typescript@~5.8.3:
+typescript@^5.0.4, typescript@~5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
@@ -10956,6 +11855,11 @@ uc.micro@^2.0.0, uc.micro@^2.1.0:
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
+uglify-js@^3.1.4:
+ version "3.19.3"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f"
+ integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==
+
uid-safe@2.1.5:
version "2.1.5"
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
@@ -10985,6 +11889,14 @@ underscore.deep@~0.5.1:
resolved "https://registry.yarnpkg.com/underscore.deep/-/underscore.deep-0.5.3.tgz#210969d58025339cecabd2a2ad8c3e8925e5c095"
integrity sha512-4OuSOlFNkiVFVc3khkeG112Pdu1gbitMj7t9B9ENb61uFmN70Jq7Iluhi3oflcSgexkKfDdJ5XAJET2gEq6ikA==
+underscore.string@~3.3.4:
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.6.tgz#ad8cf23d7423cb3b53b898476117588f4e2f9159"
+ integrity sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==
+ dependencies:
+ sprintf-js "^1.1.1"
+ util-deprecate "^1.0.2"
+
underscore@~1.13.1:
version "1.13.7"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.7.tgz#970e33963af9a7dda228f17ebe8399e5fbe63a10"
@@ -11007,11 +11919,26 @@ undici@^5.21.2:
dependencies:
"@fastify/busboy" "^2.0.0"
+undici@^7.10.0:
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-7.11.0.tgz#8e13a54f62afa756666c0590c38b3866e286d0b3"
+ integrity sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==
+
unicorn-magic@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104"
integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+universalify@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
+ integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
+
universalify@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
@@ -11039,6 +11966,14 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+url-parse@^1.5.3:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+ integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
+ dependencies:
+ querystringify "^2.1.1"
+ requires-port "^1.0.0"
+
ut_metadata@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/ut_metadata/-/ut_metadata-4.0.3.tgz#f5c38e89dfb2291f718cd4a1f7900b27144b62ac"
@@ -11072,7 +12007,7 @@ utif2@^4.0.1:
dependencies:
pako "^1.0.11"
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
@@ -11093,7 +12028,7 @@ utp-native@^2.5.3:
timeout-refresh "^1.0.0"
unordered-set "^2.0.1"
-uue@^3.1.0:
+uue@3.1.2, uue@^3.1.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/uue/-/uue-3.1.2.tgz#e99368414e87200012eb37de4dbaebaa1c742ad2"
integrity sha512-axKLXVqwtdI/czrjG0X8hyV1KLgeWx8F4KvSbvVCnS+RUvsQMGRjx0kfuZDXXqj0LYvVJmx3B9kWlKtEdRrJLg==
@@ -11136,6 +12071,11 @@ validator@~13.12.0:
resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f"
integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==
+value-or-function@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-4.0.0.tgz#70836b6a876a010dc3a2b884e7902e9db064378d"
+ integrity sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==
+
vary@^1, vary@^1.1.2, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -11150,11 +12090,78 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+vinyl-contents@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-contents/-/vinyl-contents-2.0.0.tgz#cc2ba4db3a36658d069249e9e36d9e2b41935d89"
+ integrity sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==
+ dependencies:
+ bl "^5.0.0"
+ vinyl "^3.0.0"
+
+vinyl-fs@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-4.0.2.tgz#d46557653e4a7109f29d626a9cf478680c7f8c70"
+ integrity sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==
+ dependencies:
+ fs-mkdirp-stream "^2.0.1"
+ glob-stream "^8.0.3"
+ graceful-fs "^4.2.11"
+ iconv-lite "^0.6.3"
+ is-valid-glob "^1.0.0"
+ lead "^4.0.0"
+ normalize-path "3.0.0"
+ resolve-options "^2.0.0"
+ stream-composer "^1.0.2"
+ streamx "^2.14.0"
+ to-through "^3.0.0"
+ value-or-function "^4.0.0"
+ vinyl "^3.0.1"
+ vinyl-sourcemap "^2.0.0"
+
+vinyl-sourcemap@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz#422f410a0ea97cb54cebd698d56a06d7a22e0277"
+ integrity sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==
+ dependencies:
+ convert-source-map "^2.0.0"
+ graceful-fs "^4.2.10"
+ now-and-later "^3.0.0"
+ streamx "^2.12.5"
+ vinyl "^3.0.0"
+ vinyl-contents "^2.0.0"
+
+vinyl@^3.0.0, vinyl@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-3.0.1.tgz#5f5ff85255bda2b5da25e4b3bd80b3fc077fb5a9"
+ integrity sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==
+ dependencies:
+ clone "^2.1.2"
+ remove-trailing-separator "^1.1.0"
+ replace-ext "^2.0.0"
+ teex "^1.0.1"
+
void-elements@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
+w3c-xmlserializer@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c"
+ integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==
+ dependencies:
+ xml-name-validator "^5.0.0"
+
+walk-sync@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-2.2.0.tgz#80786b0657fcc8c0e1c0b1a042a09eae2966387a"
+ integrity sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==
+ dependencies:
+ "@types/minimatch" "^3.0.3"
+ ensure-posix-path "^1.1.0"
+ matcher-collection "^2.0.0"
+ minimatch "^3.0.4"
+
web-resource-inliner@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz#df0822f0a12028805fe80719ed52ab6526886e02"
@@ -11184,6 +12191,11 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+webidl-conversions@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
+ integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
+
webrtc-polyfill@^1.1.10:
version "1.1.10"
resolved "https://registry.yarnpkg.com/webrtc-polyfill/-/webrtc-polyfill-1.1.10.tgz#1a140c42afd9bcd041a63174810795b35be5e26d"
@@ -11239,11 +12251,31 @@ webtorrent@^2.5.17:
optionalDependencies:
utp-native "^2.5.3"
+whatwg-encoding@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5"
+ integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==
+ dependencies:
+ iconv-lite "0.6.3"
+
whatwg-fetch@^3.4.1:
version "3.6.20"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
+whatwg-mimetype@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a"
+ integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==
+
+whatwg-url@^14.0.0:
+ version "14.2.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663"
+ integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==
+ dependencies:
+ tr46 "^5.1.0"
+ webidl-conversions "^7.0.0"
+
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
@@ -11401,6 +12433,11 @@ word-wrap@^1.2.5:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
+wordwrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
+
workerpool@^6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544"
@@ -11479,6 +12516,11 @@ xml-js@^1.6.11:
dependencies:
sax "^1.2.4"
+xml-name-validator@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673"
+ integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==
+
xml-parse-from-string@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
@@ -11505,6 +12547,11 @@ xmlbuilder@~11.0.0:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+xmlchars@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+ integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
xmlhttprequest-ssl@~2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz#e9e8023b3f29ef34b97a859f584c5e6c61418e23"