Add form validator translations
authorChocobozzz <me@florianbigard.com>
Tue, 5 Jun 2018 13:01:45 +0000 (15:01 +0200)
committerChocobozzz <me@florianbigard.com>
Tue, 5 Jun 2018 13:02:27 +0000 (15:02 +0200)
40 files changed:
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
client/src/app/+admin/users/user-edit/user-create.component.ts
client/src/app/+admin/users/user-edit/user-update.component.ts
client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.scss
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts
client/src/app/app.module.ts
client/src/app/login/login.component.ts
client/src/app/reset-password/reset-password.component.ts
client/src/app/shared/forms/form-validators/custom-config-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/custom-config.ts [deleted file]
client/src/app/shared/forms/form-validators/form-validator.service.ts
client/src/app/shared/forms/form-validators/index.ts
client/src/app/shared/forms/form-validators/login-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/login.ts [deleted file]
client/src/app/shared/forms/form-validators/reset-password-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/reset-password.ts [deleted file]
client/src/app/shared/forms/form-validators/user-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/user.ts [deleted file]
client/src/app/shared/forms/form-validators/validator-message.ts [deleted file]
client/src/app/shared/forms/form-validators/video-abuse-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/video-abuse.ts [deleted file]
client/src/app/shared/forms/form-validators/video-channel-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/video-channel.ts [deleted file]
client/src/app/shared/forms/form-validators/video-comment-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/video-comment.ts [deleted file]
client/src/app/shared/forms/form-validators/video-validators.service.ts [new file with mode: 0644]
client/src/app/shared/forms/form-validators/video.ts [deleted file]
client/src/app/shared/shared.module.ts
client/src/app/signup/signup.component.ts
client/src/app/videos/+video-edit/shared/video-edit.component.ts
client/src/app/videos/+video-watch/comment/video-comment-add.component.ts
client/src/app/videos/+video-watch/modal/video-report.component.ts
client/src/locale/source/messages_en_US.xml
client/src/locale/target/messages_fr.xml
client/src/main.ts

index 4263b7b5facfc9246ea84be0222863c715dc6207..a0bd01e5e135f5cc60bf2761c0306cb7a52fcdd3 100644 (file)
@@ -207,7 +207,7 @@ Check this checkbox, save the configuration and test with a video URL of your in
       <div i18n class="inner-form-title">Cache</div>
 
       <div class="form-group">
-        <label i18n for="cachePreviewsSize">Preview cache size</label>
+        <label i18n for="cachePreviewsSize">Previews cache size</label>
         <my-help
           helpType="custom" i18n-customHtml
           customHtml="Previews are not federated. We fetch them directly from the origin instance and cache them."
index f2a3464cb83ad991c8121e68ed53388bbdf85eed..7b3e72803592f51c95955bf570df15f9a20acd64 100644 (file)
@@ -1,19 +1,9 @@
 import { Component, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
 import { Router } from '@angular/router'
 import { ConfigService } from '@app/+admin/config/shared/config.service'
 import { ConfirmService } from '@app/core'
 import { ServerService } from '@app/core/server/server.service'
-import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared'
-import {
-  ADMIN_EMAIL,
-  CACHE_PREVIEWS_SIZE,
-  INSTANCE_NAME,
-  INSTANCE_SHORT_DESCRIPTION,
-  SERVICES_TWITTER_USERNAME,
-  SIGNUP_LIMIT,
-  TRANSCODING_THREADS
-} from '@app/shared/forms/form-validators/custom-config'
+import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } from '@app/shared'
 import { NotificationsService } from 'angular2-notifications'
 import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
 import { I18n } from '@ngx-translate/i18n-polyfill'
@@ -50,6 +40,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private customConfigValidatorsService: CustomConfigValidatorsService,
+    private userValidatorsService: UserValidatorsService,
     private router: Router,
     private notificationsService: NotificationsService,
     private configService: ConfigService,
@@ -66,20 +58,20 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     const formGroupData = {
-      instanceName: INSTANCE_NAME,
-      instanceShortDescription: INSTANCE_SHORT_DESCRIPTION,
+      instanceName: this.customConfigValidatorsService.INSTANCE_NAME,
+      instanceShortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
       instanceDescription: null,
       instanceTerms: null,
       instanceDefaultClientRoute: null,
       instanceDefaultNSFWPolicy: null,
-      servicesTwitterUsername: SERVICES_TWITTER_USERNAME,
+      servicesTwitterUsername: this.customConfigValidatorsService.SERVICES_TWITTER_USERNAME,
       servicesTwitterWhitelisted: null,
-      cachePreviewsSize: CACHE_PREVIEWS_SIZE,
+      cachePreviewsSize: this.customConfigValidatorsService.CACHE_PREVIEWS_SIZE,
       signupEnabled: null,
-      signupLimit: SIGNUP_LIMIT,
-      adminEmail: ADMIN_EMAIL,
-      userVideoQuota: USER_VIDEO_QUOTA,
-      transcodingThreads: TRANSCODING_THREADS,
+      signupLimit: this.customConfigValidatorsService.SIGNUP_LIMIT,
+      adminEmail: this.customConfigValidatorsService.ADMIN_EMAIL,
+      userVideoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
+      transcodingThreads: this.customConfigValidatorsService.TRANSCODING_THREADS,
       transcodingEnabled: null,
       customizationJavascript: null,
       customizationCSS: null
@@ -134,11 +126,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
       const message = this.i18n('You set custom {{customizationsText}}. ', { customizationsText }) +
         this.i18n('This could lead to security issues or bugs if you do not understand it. ') +
         this.i18n('Are you sure you want to update the configuration?')
-      const label = this.i18n(
-        'Please type "I understand the {{customizationsText}} I set" to confirm.',
-        { customizationsText }
-      )
-      const expectedInputValue = this.i18n('I understand the {{customizationsText}} I set', { customizationsText })
+
+      const label = this.i18n('Please type') + ` "I understand the ${customizationsText} I set" ` + this.i18n('to confirm.')
+      const expectedInputValue = `I understand the ${customizationsText} I set`
 
       const confirmRes = await this.confirmService.confirmWithInput(message, label, expectedInputValue)
       if (confirmRes === false) return
index e5f0903b646e4b6af73265fa0d94f90d3c2938a8..c15cfb267df7c960531e3fa914efe98144e97240 100644 (file)
@@ -2,12 +2,12 @@ import { Component, OnInit } from '@angular/core'
 import { Router } from '@angular/router'
 import { NotificationsService } from 'angular2-notifications'
 import { UserService } from '../shared'
-import { USER_EMAIL, USER_PASSWORD, USER_ROLE, USER_USERNAME, USER_VIDEO_QUOTA } from '../../../shared'
 import { ServerService } from '../../../core'
 import { UserCreate, UserRole } from '../../../../../../shared'
 import { UserEdit } from './user-edit'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
 
 @Component({
   selector: 'my-user-create',
@@ -20,6 +20,7 @@ export class UserCreateComponent extends UserEdit implements OnInit {
   constructor (
     protected serverService: ServerService,
     protected formValidatorService: FormValidatorService,
+    private userValidatorsService: UserValidatorsService,
     private router: Router,
     private notificationsService: NotificationsService,
     private userService: UserService,
@@ -35,11 +36,11 @@ export class UserCreateComponent extends UserEdit implements OnInit {
     }
 
     this.buildForm({
-      username: USER_USERNAME,
-      email: USER_EMAIL,
-      password: USER_PASSWORD,
-      role: USER_ROLE,
-      videoQuota: USER_VIDEO_QUOTA
+      username: this.userValidatorsService.USER_USERNAME,
+      email: this.userValidatorsService.USER_EMAIL,
+      password: this.userValidatorsService.USER_PASSWORD,
+      role: this.userValidatorsService.USER_ROLE,
+      videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA
     }, defaultValues)
   }
 
index f8073c928341b2962d8f9eb8c5ef6d371a385eb4..3e60991d2e218722d17e0749f38abc207c88299e 100644 (file)
@@ -3,12 +3,13 @@ import { ActivatedRoute, Router } from '@angular/router'
 import { Subscription } from 'rxjs'
 import { NotificationsService } from 'angular2-notifications'
 import { UserService } from '../shared'
-import { User, USER_EMAIL, USER_ROLE, USER_VIDEO_QUOTA } from '../../../shared'
+import { User } from '../../../shared'
 import { ServerService } from '../../../core'
 import { UserEdit } from './user-edit'
 import { UserUpdate } from '../../../../../../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
 
 @Component({
   selector: 'my-user-update',
@@ -25,6 +26,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
   constructor (
     protected formValidatorService: FormValidatorService,
     protected serverService: ServerService,
+    private userValidatorsService: UserValidatorsService,
     private route: ActivatedRoute,
     private router: Router,
     private notificationsService: NotificationsService,
@@ -37,9 +39,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
   ngOnInit () {
     const defaultValues = { videoQuota: '-1' }
     this.buildForm({
-      email: USER_EMAIL,
-      role: USER_ROLE,
-      videoQuota: USER_VIDEO_QUOTA
+      email: this.userValidatorsService.USER_EMAIL,
+      role: this.userValidatorsService.USER_ROLE,
+      videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA
     }, defaultValues)
 
     this.paramsSub = this.route.params.subscribe(routeParams => {
index 56e644f39639e93fcf4a53c309aeb95aca7f3d2a..7be7aabc213ff4ce4ff595ce0676bd9dc958993b 100644 (file)
@@ -1,8 +1,9 @@
 import { Component, OnInit } from '@angular/core'
 import { NotificationsService } from 'angular2-notifications'
-import { FormReactive, USER_PASSWORD, UserService } from '../../../shared'
+import { FormReactive, UserService } from '../../../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
 
 @Component({
   selector: 'my-account-change-password',
@@ -14,6 +15,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private userValidatorsService: UserValidatorsService,
     private notificationsService: NotificationsService,
     private userService: UserService,
     private i18n: I18n
@@ -23,8 +25,8 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
 
   ngOnInit () {
     this.buildForm({
-      'new-password': USER_PASSWORD,
-      'new-confirmed-password': USER_PASSWORD
+      'new-password': this.userValidatorsService.USER_PASSWORD,
+      'new-confirmed-password': this.userValidatorsService.USER_PASSWORD
     })
   }
 
index bbdce5b024dfac7c5ad4a5ec6f3f8995921c9590..05c0b5ddc421dc3ad69650f8184467fc92b95d0e 100644 (file)
@@ -2,22 +2,26 @@
 
 <form role="form" (ngSubmit)="updateMyProfile()" [formGroup]="form">
 
-  <label i18n for="display-name">Display name</label>
-  <input
-    type="text" id="display-name"
-    formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
-  >
-  <div *ngIf="formErrors['display-name']" class="form-error">
-    {{ formErrors['display-name'] }}
+  <div class="form-group">
+    <label i18n for="display-name">Display name</label>
+    <input
+      type="text" id="display-name"
+      formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
+    >
+    <div *ngIf="formErrors['display-name']" class="form-error">
+      {{ formErrors['display-name'] }}
+    </div>
   </div>
 
-  <label i18n for="description">Description</label>
-  <textarea
-    id="description" formControlName="description"
-    [ngClass]="{ 'input-error': formErrors['description'] }"
-  ></textarea>
-  <div *ngIf="formErrors.description" class="form-error">
-    {{ formErrors.description }}
+  <div class="form-group">
+    <label i18n for="description">Description</label>
+    <textarea
+      id="description" formControlName="description"
+      [ngClass]="{ 'input-error': formErrors['description'] }"
+    ></textarea>
+    <div *ngIf="formErrors.description" class="form-error">
+      {{ formErrors.description }}
+    </div>
   </div>
 
   <input type="submit" i18n-value value="Update my profile" [disabled]="!form.valid">
index fc2b92c89cc7a92a27991cee3aec6511397d58a3..6aabb60f4fb020072c029fe1c48fe3f8d134fe76 100644 (file)
@@ -1,11 +1,14 @@
 @import '_variables';
 @import '_mixins';
 
+.form-group:first-child {
+  margin-bottom: 15px;
+}
+
 input[type=text] {
   @include peertube-input-text(340px);
 
   display: block;
-  margin-bottom: 15px;
 }
 
 textarea {
index 1fe337da0d51fcd87c103fc16204d44a25c6861a..400c3b889e380ccb6a1d2508a679684fd10454e8 100644 (file)
@@ -1,10 +1,11 @@
 import { Component, Input, OnInit } from '@angular/core'
 import { NotificationsService } from 'angular2-notifications'
-import { FormReactive, USER_DESCRIPTION, USER_DISPLAY_NAME, UserService } from '../../../shared'
+import { FormReactive, UserService } from '../../../shared'
 import { User } from '@app/shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
 import { Subject } from 'rxjs/Subject'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
 
 @Component({
   selector: 'my-account-profile',
@@ -19,6 +20,7 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private userValidatorsService: UserValidatorsService,
     private notificationsService: NotificationsService,
     private userService: UserService,
     private i18n: I18n
@@ -28,8 +30,8 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      'display-name': USER_DISPLAY_NAME,
-      description: USER_DESCRIPTION
+      'display-name': this.userValidatorsService.USER_DISPLAY_NAME,
+      description: this.userValidatorsService.USER_DESCRIPTION
     })
 
     this.userInformationLoaded.subscribe(() => {
index e38eaae9c876da5f5c90b124dd5c712f5bd4115a..c0eaa476377c8d467ca941ffaf09ce014d2d14d1 100644 (file)
@@ -3,15 +3,11 @@ import { Router } from '@angular/router'
 import { NotificationsService } from 'angular2-notifications'
 import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
 import { VideoChannelCreate } from '../../../../../shared/models/videos'
-import {
-  VIDEO_CHANNEL_DESCRIPTION,
-  VIDEO_CHANNEL_DISPLAY_NAME,
-  VIDEO_CHANNEL_SUPPORT
-} from '@app/shared/forms/form-validators/video-channel'
 import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
 import { AuthService } from '@app/core'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
 
 @Component({
   selector: 'my-account-video-channel-create',
@@ -24,6 +20,7 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE
   constructor (
     protected formValidatorService: FormValidatorService,
     private authService: AuthService,
+    private videoChannelValidatorsService: VideoChannelValidatorsService,
     private notificationsService: NotificationsService,
     private router: Router,
     private videoChannelService: VideoChannelService,
@@ -34,9 +31,9 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE
 
   ngOnInit () {
     this.buildForm({
-      'display-name': VIDEO_CHANNEL_DISPLAY_NAME,
-      description: VIDEO_CHANNEL_DESCRIPTION,
-      support: VIDEO_CHANNEL_SUPPORT
+      'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME,
+      description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION,
+      support: this.videoChannelValidatorsService.VIDEO_CHANNEL_SUPPORT
     })
   }
 
index eda03374ad9a4d4d431ec8a6f34638cc1cdf3ca6..1510c5015f9a7e68bd20018006b8dba60f40e67e 100644 (file)
@@ -3,17 +3,13 @@ import { ActivatedRoute, Router } from '@angular/router'
 import { NotificationsService } from 'angular2-notifications'
 import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
 import { VideoChannelUpdate } from '../../../../../shared/models/videos'
-import {
-  VIDEO_CHANNEL_DESCRIPTION,
-  VIDEO_CHANNEL_DISPLAY_NAME,
-  VIDEO_CHANNEL_SUPPORT
-} from '@app/shared/forms/form-validators/video-channel'
 import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
 import { Subscription } from 'rxjs'
 import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
 import { AuthService } from '@app/core'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
 
 @Component({
   selector: 'my-account-video-channel-update',
@@ -29,6 +25,7 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
   constructor (
     protected formValidatorService: FormValidatorService,
     private authService: AuthService,
+    private videoChannelValidatorsService: VideoChannelValidatorsService,
     private notificationsService: NotificationsService,
     private router: Router,
     private route: ActivatedRoute,
@@ -40,9 +37,9 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
 
   ngOnInit () {
     this.buildForm({
-      'display-name': VIDEO_CHANNEL_DISPLAY_NAME,
-      description: VIDEO_CHANNEL_DESCRIPTION,
-      support: VIDEO_CHANNEL_SUPPORT
+      'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME,
+      description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION,
+      support: this.videoChannelValidatorsService.VIDEO_CHANNEL_SUPPORT
     })
 
     this.paramsSub = this.route.params.subscribe(routeParams => {
index 44552021f3aedcbb351f35c52d4c00b239c14552..9992b9c44e083b9843bd683b5141ebf75156b575 100644 (file)
@@ -17,6 +17,7 @@ import { SharedModule } from './shared'
 import { SignupModule } from './signup'
 import { VideosModule } from './videos'
 import { buildFileLocale, getDefaultLocale } from '../../../shared/models/i18n'
+import { environment } from '../environments/environment'
 
 export function metaFactory (serverService: ServerService): MetaLoader {
   return new MetaStaticLoader({
@@ -66,6 +67,11 @@ export function metaFactory (serverService: ServerService): MetaLoader {
     {
       provide: TRANSLATIONS,
       useFactory: (locale) => {
+        // On dev mode, test locales
+        if (environment.production === false && window.location.search === '?lang=fr') {
+          return require(`raw-loader!../locale/target/messages_fr.xml`)
+        }
+
         const fileLocale = buildFileLocale(locale)
 
         // Default locale, nothing to translate
index f7aad06e89075a56283dc492d46ace00f70793d7..a91522db367e41460592deefd6388ea72f7e7be8 100644 (file)
@@ -7,7 +7,7 @@ import { AuthService } from '../core'
 import { FormReactive } from '../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
-import { LOGIN_PASSWORD, LOGIN_USERNAME } from '@app/shared/forms/form-validators/login'
+import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service'
 
 @Component({
   selector: 'my-login',
@@ -24,6 +24,7 @@ export class LoginComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private loginValidatorsService: LoginValidatorsService,
     private authService: AuthService,
     private userService: UserService,
     private serverService: ServerService,
@@ -40,8 +41,8 @@ export class LoginComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      username: LOGIN_USERNAME,
-      password: LOGIN_PASSWORD
+      username: this.loginValidatorsService.LOGIN_USERNAME,
+      password: this.loginValidatorsService.LOGIN_PASSWORD
     })
   }
 
index 58e086f4548a4f3f8c0d21574eca1d6364146810..cb4a634f13701dea6cdd635c139cb18ada5a359d 100644 (file)
@@ -1,12 +1,12 @@
 import { Component, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
-import { USER_PASSWORD, UserService } from '@app/shared'
+import { UserService, UserValidatorsService } from '@app/shared'
 import { NotificationsService } from 'angular2-notifications'
 import { AuthService } from '../core'
 import { FormReactive } from '../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
-import { RESET_PASSWORD_CONFIRM } from '@app/shared/forms/form-validators/reset-password'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { ResetPasswordValidatorsService } from '@app/shared/forms/form-validators/reset-password-validators.service'
 
 @Component({
   selector: 'my-login',
@@ -20,6 +20,8 @@ export class ResetPasswordComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private resetPasswordValidatorsService: ResetPasswordValidatorsService,
+    private userValidatorsService: UserValidatorsService,
     private authService: AuthService,
     private userService: UserService,
     private notificationsService: NotificationsService,
@@ -32,8 +34,8 @@ export class ResetPasswordComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      password: USER_PASSWORD,
-      'password-confirm': RESET_PASSWORD_CONFIRM
+      password: this.userValidatorsService.USER_PASSWORD,
+      'password-confirm': this.resetPasswordValidatorsService.RESET_PASSWORD_CONFIRM
     })
 
     this.userId = this.route.snapshot.queryParams['userId']
diff --git a/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts b/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts
new file mode 100644 (file)
index 0000000..1b36bbc
--- /dev/null
@@ -0,0 +1,72 @@
+import { Validators } from '@angular/forms'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { BuildFormValidator } from '@app/shared'
+import { Injectable } from '@angular/core'
+
+@Injectable()
+export class CustomConfigValidatorsService {
+  readonly INSTANCE_NAME: BuildFormValidator
+  readonly INSTANCE_SHORT_DESCRIPTION: BuildFormValidator
+  readonly SERVICES_TWITTER_USERNAME: BuildFormValidator
+  readonly CACHE_PREVIEWS_SIZE: BuildFormValidator
+  readonly SIGNUP_LIMIT: BuildFormValidator
+  readonly ADMIN_EMAIL: BuildFormValidator
+  readonly TRANSCODING_THREADS: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.INSTANCE_NAME = {
+      VALIDATORS: [ Validators.required ],
+      MESSAGES: {
+        'required': this.i18n('Instance name is required.')
+      }
+    }
+
+    this.INSTANCE_SHORT_DESCRIPTION = {
+      VALIDATORS: [ Validators.max(250) ],
+      MESSAGES: {
+        'max': this.i18n('Short description should not be longer than 250 characters.')
+      }
+    }
+
+    this.SERVICES_TWITTER_USERNAME = {
+      VALIDATORS: [ Validators.required ],
+      MESSAGES: {
+        'required': this.i18n('Twitter username is required.')
+      }
+    }
+
+    this.CACHE_PREVIEWS_SIZE = {
+      VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
+      MESSAGES: {
+        'required': this.i18n('Previews cache size is required.'),
+        'min': this.i18n('Previews cache size must be greater than 1.'),
+        'pattern': this.i18n('Previews cache size must be a number.')
+      }
+    }
+
+    this.SIGNUP_LIMIT = {
+      VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
+      MESSAGES: {
+        'required': this.i18n('Signup limit is required.'),
+        'min': this.i18n('Signup limit must be greater than 1.'),
+        'pattern': this.i18n('Signup limit must be a number.')
+      }
+    }
+
+    this.ADMIN_EMAIL = {
+      VALIDATORS: [ Validators.required, Validators.email ],
+      MESSAGES: {
+        'required': this.i18n('Admin email is required.'),
+        'email': this.i18n('Admin email must be valid.')
+      }
+    }
+
+    this.TRANSCODING_THREADS = {
+      VALIDATORS: [ Validators.required, Validators.min(1) ],
+      MESSAGES: {
+        'required': this.i18n('Transcoding threads is required.'),
+        'min': this.i18n('Transcoding threads must be greater than 1.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/custom-config.ts b/client/src/app/shared/forms/form-validators/custom-config.ts
deleted file mode 100644 (file)
index e3d9a4c..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const INSTANCE_NAME = {
-  VALIDATORS: [ Validators.required ],
-  MESSAGES: {
-    'required': 'Instance name is required.'
-  }
-}
-
-export const INSTANCE_SHORT_DESCRIPTION = {
-  VALIDATORS: [ Validators.max(250) ],
-  MESSAGES: {
-    'max': 'Short description should not be longer than 250 characters.'
-  }
-}
-
-export const SERVICES_TWITTER_USERNAME = {
-  VALIDATORS: [ Validators.required ],
-  MESSAGES: {
-    'required': 'Twitter username is required.'
-  }
-}
-
-export const CACHE_PREVIEWS_SIZE = {
-  VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
-  MESSAGES: {
-    'required': 'Preview cache size is required.',
-    'min': 'Preview cache size must be greater than 1.',
-    'pattern': 'Preview cache size must be a number.'
-  }
-}
-
-export const SIGNUP_LIMIT = {
-  VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
-  MESSAGES: {
-    'required': 'Signup limit is required.',
-    'min': 'Signup limit must be greater than 1.',
-    'pattern': 'Preview cache size must be a number.'
-  }
-}
-
-export const ADMIN_EMAIL = {
-  VALIDATORS: [ Validators.required, Validators.email ],
-  MESSAGES: {
-    'required': 'Admin email is required.',
-    'email': 'Admin email must be valid.'
-  }
-}
-
-export const TRANSCODING_THREADS = {
-  VALIDATORS: [ Validators.required, Validators.min(1) ],
-  MESSAGES: {
-    'required': 'Transcoding threads is required.',
-    'min': 'Transcoding threads must be greater than 1.'
-  }
-}
index 5c3d3e4bddb8ccd783b0e2426dd0914fce9a66d9..d10e17ca7659cd3170982d6aa866ebc88efcac7a 100644 (file)
@@ -3,11 +3,12 @@ import { Injectable } from '@angular/core'
 import { FormReactiveErrors, FormReactiveValidationMessages } from '@app/shared/forms/form-reactive'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 
+export type BuildFormValidator = {
+  VALIDATORS: ValidatorFn[],
+  MESSAGES: { [ name: string ]: string }
+}
 export type BuildFormArgument = {
-  [ id: string ]: {
-    VALIDATORS: ValidatorFn[],
-    MESSAGES: { [ name: string ]: string }
-  }
+  [ id: string ]: BuildFormValidator
 }
 export type BuildFormDefaultValues = {
   [ name: string ]: string | string[]
index cf544b2a9b44ce5cfd7dcc48a57f0e1444bb43c4..4876830884d77c59a76390ec238c72c12a31ca97 100644 (file)
@@ -1,5 +1,10 @@
+export * from './custom-config-validators.service'
 export * from './form-validator.service'
 export * from './host'
-export * from './user'
-export * from './video-abuse'
-export * from './video'
+export * from './login-validators.service'
+export * from './reset-password-validators.service'
+export * from './user-validators.service'
+export * from './video-abuse-validators.service'
+export * from './video-channel-validators.service'
+export * from './video-comment-validators.service'
+export * from './video-validators.service'
diff --git a/client/src/app/shared/forms/form-validators/login-validators.service.ts b/client/src/app/shared/forms/form-validators/login-validators.service.ts
new file mode 100644 (file)
index 0000000..9d68f83
--- /dev/null
@@ -0,0 +1,30 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class LoginValidatorsService {
+  readonly LOGIN_USERNAME: BuildFormValidator
+  readonly LOGIN_PASSWORD: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.LOGIN_USERNAME = {
+      VALIDATORS: [
+        Validators.required
+      ],
+      MESSAGES: {
+        'required': this.i18n('Username is required.')
+      }
+    }
+
+    this.LOGIN_PASSWORD = {
+      VALIDATORS: [
+        Validators.required
+      ],
+      MESSAGES: {
+        'required': this.i18n('Password is required.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/login.ts b/client/src/app/shared/forms/form-validators/login.ts
deleted file mode 100644 (file)
index f37f8d2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const LOGIN_USERNAME = {
-  VALIDATORS: [
-    Validators.required
-  ],
-  MESSAGES: {
-    'required': 'Username is required.'
-  }
-}
-export const LOGIN_PASSWORD = {
-  VALIDATORS: [
-    Validators.required
-  ],
-  MESSAGES: {
-    'required': 'Password is required.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/reset-password-validators.service.ts b/client/src/app/shared/forms/form-validators/reset-password-validators.service.ts
new file mode 100644 (file)
index 0000000..df20625
--- /dev/null
@@ -0,0 +1,20 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class ResetPasswordValidatorsService {
+  readonly RESET_PASSWORD_CONFIRM: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.RESET_PASSWORD_CONFIRM = {
+      VALIDATORS: [
+        Validators.required
+      ],
+      MESSAGES: {
+        'required': this.i18n('Confirmation of the password is required.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/reset-password.ts b/client/src/app/shared/forms/form-validators/reset-password.ts
deleted file mode 100644 (file)
index 7dafdef..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const RESET_PASSWORD_CONFIRM = {
-  VALIDATORS: [
-    Validators.required
-  ],
-  MESSAGES: {
-    'required': 'Confirmation of the password is required.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/user-validators.service.ts b/client/src/app/shared/forms/form-validators/user-validators.service.ts
new file mode 100644 (file)
index 0000000..bb6ff20
--- /dev/null
@@ -0,0 +1,93 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { BuildFormValidator } from '@app/shared'
+import { Injectable } from '@angular/core'
+
+@Injectable()
+export class UserValidatorsService {
+  readonly USER_USERNAME: BuildFormValidator
+  readonly USER_EMAIL: BuildFormValidator
+  readonly USER_PASSWORD: BuildFormValidator
+  readonly USER_VIDEO_QUOTA: BuildFormValidator
+  readonly USER_ROLE: BuildFormValidator
+  readonly USER_DISPLAY_NAME: BuildFormValidator
+  readonly USER_DESCRIPTION: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+
+    this.USER_USERNAME = {
+      VALIDATORS: [
+        Validators.required,
+        Validators.minLength(3),
+        Validators.maxLength(20),
+        Validators.pattern(/^[a-z0-9._]+$/)
+      ],
+      MESSAGES: {
+        'required': this.i18n('Username is required.'),
+        'minlength': this.i18n('Username must be at least 3 characters long.'),
+        'maxlength': this.i18n('Username cannot be more than 20 characters long.'),
+        'pattern': this.i18n('Username should be only lowercase alphanumeric characters.')
+      }
+    }
+
+    this.USER_EMAIL = {
+      VALIDATORS: [ Validators.required, Validators.email ],
+      MESSAGES: {
+        'required': this.i18n('Email is required.'),
+        'email': this.i18n('Email must be valid.')
+      }
+    }
+
+    this.USER_PASSWORD = {
+      VALIDATORS: [
+        Validators.required,
+        Validators.minLength(6),
+        Validators.maxLength(255)
+      ],
+      MESSAGES: {
+        'required': this.i18n('Password is required.'),
+        'minlength': this.i18n('Password must be at least 6 characters long.'),
+        'maxlength': this.i18n('Password cannot be more than 255 characters long.')
+      }
+    }
+
+    this.USER_VIDEO_QUOTA = {
+      VALIDATORS: [ Validators.required, Validators.min(-1) ],
+      MESSAGES: {
+        'required': this.i18n('Video quota is required.'),
+        'min': this.i18n('Quota must be greater than -1.')
+      }
+    }
+
+    this.USER_ROLE = {
+      VALIDATORS: [ Validators.required ],
+      MESSAGES: {
+        'required': this.i18n('User role is required.')
+      }
+    }
+
+    this.USER_DISPLAY_NAME = {
+      VALIDATORS: [
+        Validators.required,
+        Validators.minLength(3),
+        Validators.maxLength(120)
+      ],
+      MESSAGES: {
+        'required': this.i18n('Display name is required.'),
+        'minlength': this.i18n('Display name must be at least 3 characters long.'),
+        'maxlength': this.i18n('Display name cannot be more than 120 characters long.')
+      }
+    }
+
+    this.USER_DESCRIPTION = {
+      VALIDATORS: [
+        Validators.minLength(3),
+        Validators.maxLength(250)
+      ],
+      MESSAGES: {
+        'minlength': this.i18n('Description must be at least 3 characters long.'),
+        'maxlength': this.i18n('Description cannot be more than 250 characters long.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/user.ts b/client/src/app/shared/forms/form-validators/user.ts
deleted file mode 100644 (file)
index 0973f1b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const USER_USERNAME = {
-  VALIDATORS: [
-    Validators.required,
-    Validators.minLength(3),
-    Validators.maxLength(20),
-    Validators.pattern(/^[a-z0-9._]+$/)
-  ],
-  MESSAGES: {
-    'required': 'Username is required.',
-    'minlength': 'Username must be at least 3 characters long.',
-    'maxlength': 'Username cannot be more than 20 characters long.',
-    'pattern': 'Username should be only lowercase alphanumeric characters.'
-  }
-}
-export const USER_EMAIL = {
-  VALIDATORS: [ Validators.required, Validators.email ],
-  MESSAGES: {
-    'required': 'Email is required.',
-    'email': 'Email must be valid.'
-  }
-}
-export const USER_PASSWORD = {
-  VALIDATORS: [
-    Validators.required,
-    Validators.minLength(6),
-    Validators.maxLength(255)
-  ],
-  MESSAGES: {
-    'required': 'Password is required.',
-    'minlength': 'Password must be at least 6 characters long.',
-    'maxlength': 'Password cannot be more than 255 characters long.'
-  }
-}
-export const USER_VIDEO_QUOTA = {
-  VALIDATORS: [ Validators.required, Validators.min(-1) ],
-  MESSAGES: {
-    'required': 'Video quota is required.',
-    'min': 'Quota must be greater than -1.'
-  }
-}
-export const USER_ROLE = {
-  VALIDATORS: [ Validators.required ],
-  MESSAGES: {
-    'required': 'User role is required.'
-  }
-}
-export const USER_DISPLAY_NAME = {
-  VALIDATORS: [
-    Validators.required,
-    Validators.minLength(3),
-    Validators.maxLength(120)
-  ],
-  MESSAGES: {
-    'required': 'Display name is required.',
-    'minlength': 'Display name must be at least 3 characters long.',
-    'maxlength': 'Display name cannot be more than 120 characters long.'
-  }
-}
-export const USER_DESCRIPTION = {
-  VALIDATORS: [
-    Validators.minLength(3),
-    Validators.maxLength(250)
-  ],
-  MESSAGES: {
-    'minlength': 'Description must be at least 3 characters long.',
-    'maxlength': 'Description cannot be more than 250 characters long.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/validator-message.ts b/client/src/app/shared/forms/form-validators/validator-message.ts
deleted file mode 100644 (file)
index 5ce4583..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-export type ValidatorMessage = {
-  [ id: string ]: {
-    [ error: string ]: string
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/video-abuse-validators.service.ts b/client/src/app/shared/forms/form-validators/video-abuse-validators.service.ts
new file mode 100644 (file)
index 0000000..774e6a4
--- /dev/null
@@ -0,0 +1,20 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class VideoAbuseValidatorsService {
+  readonly VIDEO_ABUSE_REASON: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.VIDEO_ABUSE_REASON = {
+      VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(300) ],
+      MESSAGES: {
+        'required': this.i18n('Report reason is required.'),
+        'minlength': this.i18n('Report reason must be at least 2 characters long.'),
+        'maxlength': this.i18n('Report reason cannot be more than 300 characters long.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/video-abuse.ts b/client/src/app/shared/forms/form-validators/video-abuse.ts
deleted file mode 100644 (file)
index 4b2a2b7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const VIDEO_ABUSE_REASON = {
-  VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(300) ],
-  MESSAGES: {
-    'required': 'Report reason is required.',
-    'minlength': 'Report reason must be at least 2 characters long.',
-    'maxlength': 'Report reason cannot be more than 300 characters long.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts b/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts
new file mode 100644 (file)
index 0000000..28b063f
--- /dev/null
@@ -0,0 +1,48 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class VideoChannelValidatorsService {
+  readonly VIDEO_CHANNEL_DISPLAY_NAME: BuildFormValidator
+  readonly VIDEO_CHANNEL_DESCRIPTION: BuildFormValidator
+  readonly VIDEO_CHANNEL_SUPPORT: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.VIDEO_CHANNEL_DISPLAY_NAME = {
+      VALIDATORS: [
+        Validators.required,
+        Validators.minLength(3),
+        Validators.maxLength(120)
+      ],
+      MESSAGES: {
+        'required': i18n('Display name is required.'),
+        'minlength': i18n('Display name must be at least 3 characters long.'),
+        'maxlength': i18n('Display name cannot be more than 120 characters long.')
+      }
+    }
+
+    this.VIDEO_CHANNEL_DESCRIPTION = {
+      VALIDATORS: [
+        Validators.minLength(3),
+        Validators.maxLength(500)
+      ],
+      MESSAGES: {
+        'minlength': i18n('Description must be at least 3 characters long.'),
+        'maxlength': i18n('Description cannot be more than 500 characters long.')
+      }
+    }
+
+    this.VIDEO_CHANNEL_SUPPORT = {
+      VALIDATORS: [
+        Validators.minLength(3),
+        Validators.maxLength(500)
+      ],
+      MESSAGES: {
+        'minlength': i18n('Support text must be at least 3 characters long.'),
+        'maxlength': i18n('Support text cannot be more than 500 characters long.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/video-channel.ts b/client/src/app/shared/forms/form-validators/video-channel.ts
deleted file mode 100644 (file)
index 2185cda..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const VIDEO_CHANNEL_DISPLAY_NAME = {
-  VALIDATORS: [
-    Validators.required,
-    Validators.minLength(3),
-    Validators.maxLength(120)
-  ],
-  MESSAGES: {
-    'required': 'Display name is required.',
-    'minlength': 'Display name must be at least 3 characters long.',
-    'maxlength': 'Display name cannot be more than 120 characters long.'
-  }
-}
-export const VIDEO_CHANNEL_DESCRIPTION = {
-  VALIDATORS: [
-    Validators.minLength(3),
-    Validators.maxLength(500)
-  ],
-  MESSAGES: {
-    'minlength': 'Description must be at least 3 characters long.',
-    'maxlength': 'Description cannot be more than 500 characters long.'
-  }
-}
-export const VIDEO_CHANNEL_SUPPORT = {
-  VALIDATORS: [
-    Validators.minLength(3),
-    Validators.maxLength(500)
-  ],
-  MESSAGES: {
-    'minlength': 'Support text must be at least 3 characters long.',
-    'maxlength': 'Support text cannot be more than 500 characters long.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/video-comment-validators.service.ts b/client/src/app/shared/forms/form-validators/video-comment-validators.service.ts
new file mode 100644 (file)
index 0000000..45c7081
--- /dev/null
@@ -0,0 +1,20 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class VideoCommentValidatorsService {
+  readonly VIDEO_COMMENT_TEXT: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+    this.VIDEO_COMMENT_TEXT = {
+      VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ],
+      MESSAGES: {
+        'required': this.i18n('Comment is required.'),
+        'minlength': this.i18n('Comment must be at least 2 characters long.'),
+        'maxlength': this.i18n('Comment cannot be more than 3000 characters long.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/video-comment.ts b/client/src/app/shared/forms/form-validators/video-comment.ts
deleted file mode 100644 (file)
index 290d831..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const VIDEO_COMMENT_TEXT = {
-  VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ],
-  MESSAGES: {
-    'required': 'Comment is required.',
-    'minlength': 'Comment must be at least 2 characters long.',
-    'maxlength': 'Comment cannot be more than 3000 characters long.'
-  }
-}
diff --git a/client/src/app/shared/forms/form-validators/video-validators.service.ts b/client/src/app/shared/forms/form-validators/video-validators.service.ts
new file mode 100644 (file)
index 0000000..76fc5cf
--- /dev/null
@@ -0,0 +1,88 @@
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Validators } from '@angular/forms'
+import { Injectable } from '@angular/core'
+import { BuildFormValidator } from '@app/shared'
+
+@Injectable()
+export class VideoValidatorsService {
+  readonly VIDEO_NAME: BuildFormValidator
+  readonly VIDEO_PRIVACY: BuildFormValidator
+  readonly VIDEO_CATEGORY: BuildFormValidator
+  readonly VIDEO_LICENCE: BuildFormValidator
+  readonly VIDEO_LANGUAGE: BuildFormValidator
+  readonly VIDEO_IMAGE: BuildFormValidator
+  readonly VIDEO_CHANNEL: BuildFormValidator
+  readonly VIDEO_DESCRIPTION: BuildFormValidator
+  readonly VIDEO_TAGS: BuildFormValidator
+  readonly VIDEO_SUPPORT: BuildFormValidator
+
+  constructor (private i18n: I18n) {
+
+    this.VIDEO_NAME = {
+      VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(120) ],
+      MESSAGES: {
+        'required': this.i18n('Video name is required.'),
+        'minlength': this.i18n('Video name must be at least 3 characters long.'),
+        'maxlength': this.i18n('Video name cannot be more than 120 characters long.')
+      }
+    }
+
+    this.VIDEO_PRIVACY = {
+      VALIDATORS: [ Validators.required ],
+      MESSAGES: {
+        'required': this.i18n('Video privacy is required.')
+      }
+    }
+
+    this.VIDEO_CATEGORY = {
+      VALIDATORS: [ ],
+      MESSAGES: {}
+    }
+
+    this.VIDEO_LICENCE = {
+      VALIDATORS: [ ],
+      MESSAGES: {}
+    }
+
+    this.VIDEO_LANGUAGE = {
+      VALIDATORS: [ ],
+      MESSAGES: {}
+    }
+
+    this.VIDEO_IMAGE = {
+      VALIDATORS: [ ],
+      MESSAGES: {}
+    }
+
+    this.VIDEO_CHANNEL = {
+      VALIDATORS: [ Validators.required ],
+      MESSAGES: {
+        'required': this.i18n('Video channel is required.')
+      }
+    }
+
+    this.VIDEO_DESCRIPTION = {
+      VALIDATORS: [ Validators.minLength(3), Validators.maxLength(10000) ],
+      MESSAGES: {
+        'minlength': this.i18n('Video description must be at least 3 characters long.'),
+        'maxlength': this.i18n('Video description cannot be more than 10000 characters long.')
+      }
+    }
+
+    this.VIDEO_TAGS = {
+      VALIDATORS: [ Validators.minLength(2), Validators.maxLength(30) ],
+      MESSAGES: {
+        'minlength': this.i18n('A tag should be more than 2 characters long.'),
+        'maxlength': this.i18n('A tag should be less than 30 characters long.')
+      }
+    }
+
+    this.VIDEO_SUPPORT = {
+      VALIDATORS: [ Validators.minLength(3), Validators.maxLength(500) ],
+      MESSAGES: {
+        'minlength': this.i18n('Video support must be at least 3 characters long.'),
+        'maxlength': this.i18n('Video support cannot be more than 500 characters long.')
+      }
+    }
+  }
+}
diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts
deleted file mode 100644 (file)
index a986243..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-import { Validators } from '@angular/forms'
-
-export const VIDEO_NAME = {
-  VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(120) ],
-  MESSAGES: {
-    'required': 'Video name is required.',
-    'minlength': 'Video name must be at least 3 characters long.',
-    'maxlength': 'Video name cannot be more than 120 characters long.'
-  }
-}
-
-export const VIDEO_PRIVACY = {
-  VALIDATORS: [ Validators.required ],
-  MESSAGES: {
-    'required': 'Video privacy is required.'
-  }
-}
-
-export const VIDEO_CATEGORY = {
-  VALIDATORS: [ ],
-  MESSAGES: {}
-}
-
-export const VIDEO_LICENCE = {
-  VALIDATORS: [ ],
-  MESSAGES: {}
-}
-
-export const VIDEO_LANGUAGE = {
-  VALIDATORS: [ ],
-  MESSAGES: {}
-}
-
-export const VIDEO_IMAGE = {
-  VALIDATORS: [ ],
-  MESSAGES: {}
-}
-
-export const VIDEO_CHANNEL = {
-  VALIDATORS: [ Validators.required ],
-  MESSAGES: {
-    'required': 'Video channel is required.'
-  }
-}
-
-export const VIDEO_DESCRIPTION = {
-  VALIDATORS: [ Validators.minLength(3), Validators.maxLength(10000) ],
-  MESSAGES: {
-    'minlength': 'Video description must be at least 3 characters long.',
-    'maxlength': 'Video description cannot be more than 10000 characters long.'
-  }
-}
-
-export const VIDEO_TAGS = {
-  VALIDATORS: [ Validators.minLength(2), Validators.maxLength(30) ],
-  MESSAGES: {
-    'minlength': 'A tag should be more than 2 characters long.',
-    'maxlength': 'A tag should be less than 30 characters long.'
-  }
-}
-
-export const VIDEO_SUPPORT = {
-  VALIDATORS: [ Validators.minLength(3), Validators.maxLength(500) ],
-  MESSAGES: {
-    'minlength': 'Video support must be at least 3 characters long.',
-    'maxlength': 'Video support cannot be more than 500 characters long.'
-  }
-}
index 91d905ec7120eaddce89d6721ddd2db2dd731199..b85445ef54e698e11b4e87aa84c3f5751dbdbe9f 100644 (file)
@@ -35,6 +35,12 @@ import { AccountService } from '@app/shared/account/account.service'
 import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import {
+  CustomConfigValidatorsService,
+  LoginValidatorsService,
+  ResetPasswordValidatorsService,
+  UserValidatorsService, VideoAbuseValidatorsService, VideoChannelValidatorsService, VideoCommentValidatorsService, VideoValidatorsService
+} from '@app/shared/forms'
 
 @NgModule({
   imports: [
@@ -111,7 +117,17 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val
     AccountService,
     MarkdownService,
     VideoChannelService,
+
     FormValidatorService,
+    CustomConfigValidatorsService,
+    LoginValidatorsService,
+    ResetPasswordValidatorsService,
+    UserValidatorsService,
+    VideoAbuseValidatorsService,
+    VideoChannelValidatorsService,
+    VideoCommentValidatorsService,
+    VideoValidatorsService,
+
     I18n
   ]
 })
index 682e592c79704da19bad91dea1021c616ef724f2..a40f42cb11b0a2b678b9d1874d5f2118b8a8a6a8 100644 (file)
@@ -1,10 +1,9 @@
 import { Component, OnInit } from '@angular/core'
 import { Router } from '@angular/router'
 import { ServerService } from '@app/core/server'
-
 import { NotificationsService } from 'angular2-notifications'
 import { UserCreate } from '../../../../shared'
-import { FormReactive, USER_EMAIL, USER_PASSWORD, USER_USERNAME, UserService } from '../shared'
+import { FormReactive, UserService, UserValidatorsService } from '../shared'
 import { RedirectService } from '@app/core'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
@@ -32,6 +31,7 @@ export class SignupComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private userValidatorsService: UserValidatorsService,
     private router: Router,
     private notificationsService: NotificationsService,
     private userService: UserService,
@@ -48,9 +48,9 @@ export class SignupComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      username: USER_USERNAME,
-      password: USER_PASSWORD,
-      email: USER_EMAIL
+      username: this.userValidatorsService.USER_USERNAME,
+      password: this.userValidatorsService.USER_PASSWORD,
+      email: this.userValidatorsService.USER_EMAIL
     })
 
     this.serverService.configLoaded
index cd2a26ae3067bfebf1c9eeb53d85222effcfa6c0..61515c0b0cb4069b958e0294814c6cd1947b75fa 100644 (file)
@@ -1,20 +1,9 @@
 import { Component, Input, OnInit } from '@angular/core'
-import { FormGroup } from '@angular/forms'
+import { FormGroup, ValidatorFn } from '@angular/forms'
 import { ActivatedRoute, Router } from '@angular/router'
-import { VIDEO_SUPPORT } from '@app/shared'
+import { FormReactiveValidationMessages, VideoValidatorsService } from '@app/shared'
 import { NotificationsService } from 'angular2-notifications'
 import { ServerService } from '../../../core/server'
-import { VIDEO_CHANNEL } from '../../../shared/forms/form-validators'
-import { ValidatorMessage } from '../../../shared/forms/form-validators/validator-message'
-import {
-  VIDEO_CATEGORY,
-  VIDEO_DESCRIPTION,
-  VIDEO_LANGUAGE,
-  VIDEO_LICENCE,
-  VIDEO_NAME,
-  VIDEO_PRIVACY,
-  VIDEO_TAGS
-} from '../../../shared/forms/form-validators/video'
 import { VideoEdit } from '../../../shared/video/video-edit.model'
 import { map } from 'rxjs/operators'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
@@ -28,7 +17,7 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val
 export class VideoEditComponent implements OnInit {
   @Input() form: FormGroup
   @Input() formErrors: { [ id: string ]: string } = {}
-  @Input() validationMessages: ValidatorMessage = {}
+  @Input() validationMessages: FormReactiveValidationMessages = {}
   @Input() videoPrivacies = []
   @Input() userVideoChannels: { id: number, label: string, support: string }[] = []
 
@@ -37,18 +26,22 @@ export class VideoEditComponent implements OnInit {
   videoLanguages = []
   video: VideoEdit
 
-  tagValidators = VIDEO_TAGS.VALIDATORS
-  tagValidatorsMessages = VIDEO_TAGS.MESSAGES
+  tagValidators: ValidatorFn[]
+  tagValidatorsMessages: { [ name: string ]: string }
 
   error: string = null
 
   constructor (
     private formValidatorService: FormValidatorService,
+    private videoValidatorsService: VideoValidatorsService,
     private route: ActivatedRoute,
     private router: Router,
     private notificationsService: NotificationsService,
     private serverService: ServerService
-  ) { }
+  ) {
+    this.tagValidators = this.videoValidatorsService.VIDEO_TAGS.VALIDATORS
+    this.tagValidatorsMessages = this.videoValidatorsService.VIDEO_TAGS.MESSAGES
+  }
 
   updateForm () {
     const defaultValues = {
@@ -57,19 +50,19 @@ export class VideoEditComponent implements OnInit {
       tags: []
     }
     const obj = {
-      name: VIDEO_NAME,
-      privacy: VIDEO_PRIVACY,
-      channelId: VIDEO_CHANNEL,
+      name: this.videoValidatorsService.VIDEO_NAME,
+      privacy: this.videoValidatorsService.VIDEO_PRIVACY,
+      channelId: this.videoValidatorsService.VIDEO_CHANNEL,
       nsfw: null,
       commentsEnabled: null,
-      category: VIDEO_CATEGORY,
-      licence: VIDEO_LICENCE,
-      language: VIDEO_LANGUAGE,
-      description: VIDEO_DESCRIPTION,
+      category: this.videoValidatorsService.VIDEO_CATEGORY,
+      licence: this.videoValidatorsService.VIDEO_LICENCE,
+      language: this.videoValidatorsService.VIDEO_LANGUAGE,
+      description: this.videoValidatorsService.VIDEO_DESCRIPTION,
       tags: null,
       thumbnailfile: null,
       previewfile: null,
-      support: VIDEO_SUPPORT
+      support: this.videoValidatorsService.VIDEO_SUPPORT
     }
 
     this.formValidatorService.updateForm(
index c70e544a33417225619c4099afa088c55f59dcb3..46d7a4e9eb6377114ebd523fa86536f86d8690fa 100644 (file)
@@ -3,13 +3,13 @@ import { NotificationsService } from 'angular2-notifications'
 import { Observable } from 'rxjs'
 import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model'
 import { FormReactive } from '../../../shared'
-import { VIDEO_COMMENT_TEXT } from '../../../shared/forms/form-validators/video-comment'
 import { User } from '../../../shared/users'
 import { Video } from '../../../shared/video/video.model'
 import { VideoComment } from './video-comment.model'
 import { VideoCommentService } from './video-comment.service'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service'
 
 @Component({
   selector: 'my-video-comment-add',
@@ -29,6 +29,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private videoCommentValidatorsService: VideoCommentValidatorsService,
     private notificationsService: NotificationsService,
     private videoCommentService: VideoCommentService,
     private i18n: I18n
@@ -38,7 +39,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      text: VIDEO_COMMENT_TEXT
+      text: this.videoCommentValidatorsService.VIDEO_COMMENT_TEXT
     })
 
     if (this.focusOnInit === true) {
index 8641e8dfbff43e0aaa487f4044882ae5b3b20548..d9768fdac830e3e5947bd5f310aa41a0480c3a84 100644 (file)
@@ -1,12 +1,11 @@
 import { Component, Input, OnInit, ViewChild } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
 import { NotificationsService } from 'angular2-notifications'
 import { ModalDirective } from 'ngx-bootstrap/modal'
-import { FormReactive, VIDEO_ABUSE_REASON, VideoAbuseService } from '../../../shared/index'
+import { FormReactive, VideoAbuseService } from '../../../shared/index'
 import { VideoDetails } from '../../../shared/video/video-details.model'
 import { I18n } from '@ngx-translate/i18n-polyfill'
-import { FormReactiveErrors, FormReactiveValidationMessages } from '@app/shared'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/video-abuse-validators.service'
 
 @Component({
   selector: 'my-video-report',
@@ -22,6 +21,7 @@ export class VideoReportComponent extends FormReactive implements OnInit {
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private videoAbuseValidatorsService: VideoAbuseValidatorsService,
     private videoAbuseService: VideoAbuseService,
     private notificationsService: NotificationsService,
     private i18n: I18n
@@ -31,7 +31,7 @@ export class VideoReportComponent extends FormReactive implements OnInit {
 
   ngOnInit () {
     this.buildForm({
-      reason: VIDEO_ABUSE_REASON
+      reason: this.videoAbuseValidatorsService.VIDEO_ABUSE_REASON
     })
   }
 
index 9ac231954382518bedea244f5165b7ad2af4656a..08949c5647c74cdb777552e24c819ace08ed89a3 100644 (file)
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts</context>
-          <context context-type="linenumber">14</context>
+          <context context-type="linenumber">17</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/+video-channels/video-channel-about/video-channel-about.component.ts</context>
@@ -739,8 +739,8 @@ Check this checkbox, save the configuration and test with a video URL of your in
           <context context-type="sourcefile">app/+admin/config/edit-custom-config/edit-custom-config.component.ts</context>
           <context context-type="linenumber">207</context>
         </context-group>
-      </trans-unit><trans-unit id="48c189b718ed2d091e5c515bfc14b03e5ceb4f93" datatype="html">
-        <source>Preview cache size</source>
+      </trans-unit><trans-unit id="d00f6c2dcb426440a0a8cd8eec12d094fbfaf6f7" datatype="html">
+        <source>Previews cache size</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/+admin/config/edit-custom-config/edit-custom-config.component.ts</context>
           <context context-type="linenumber">210</context>
@@ -1239,7 +1239,7 @@ Check this checkbox, save the configuration and test with a video URL of your in
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts</context>
-          <context context-type="linenumber">5</context>
+          <context context-type="linenumber">6</context>
         </context-group>
       </trans-unit><trans-unit id="74728de5289ea2ff3f553bc2b48f1811680b931a" datatype="html">
         <source>Short text to tell people how they can support your channel (membership platform...).&lt;br /&gt;&lt;br /&gt;
@@ -1296,7 +1296,7 @@ When you will upload a video in this channel, the video support field will be au
         <source>Update my profile</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts</context>
-          <context context-type="linenumber">23</context>
+          <context context-type="linenumber">27</context>
         </context-group>
       </trans-unit><trans-unit id="e242e3e8608a3c4a944327eb3d5c221dc6e4e3cd" datatype="html">
         <source>
@@ -1851,8 +1851,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="b0ea97653991a80d6324423949d37b8f165a4505" datatype="html">
-        <source>Published &lt;x id="INTERPOLATION" equiv-text="{{ totalVideos }}"/&gt; videos</source>
+      <trans-unit id="369ef5e9c0dd1251abdbf699a5db408bca10777f" datatype="html">
+        <source>Published &lt;x id="INTERPOLATION" equiv-text="{{totalVideos}}"/&gt; videos</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+accounts/account-videos/account-videos.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2009,8 +2009,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="6b988bab9e171f65ed3510e8a66b9c5f7fcc5209" datatype="html">
-        <source>You set custom &lt;x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/&gt;. </source>
+      <trans-unit id="27a71a0aee65258179e90ecf0841c0a68f95beed" datatype="html">
+        <source>You set custom &lt;x id="INTERPOLATION" equiv-text="{{customizationsText}}"/&gt;. </source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2030,15 +2030,15 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="03b6bae23e3f895ed8f53e3b29fad0cafc7dd002" datatype="html">
-        <source>Please type &quot;I understand the &lt;x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/&gt; I set&quot; to confirm.</source>
+      <trans-unit id="1ae0ab69f5c19d179282c8d882fd2f3c00e29119" datatype="html">
+        <source>Please type</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="892eb3bbce40125f9ed1dc13078d2938b921ff53" datatype="html">
-        <source>I understand the &lt;x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/&gt; I set</source>
+      <trans-unit id="75f4bb68ee4c6b282abfd9d8d32be22c6202794d" datatype="html">
+        <source>to confirm.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2146,8 +2146,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="511be2e1ddb087fe7a0d95654f5f72b446d3da87" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ host }}"/&gt; is not valid</source>
+      <trans-unit id="fc5731a28a99b25c62d43333ceebb250d60aff84" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{host}}"/&gt; is not valid</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/follows/following-add/following-add.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2188,8 +2188,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="b1f6b95a2d83bc589955f2679de00ce70fa03594" datatype="html">
-        <source>Do you really want to unfollow &lt;x id="INTERPOLATION" equiv-text="{{ host }}"/&gt;?</source>
+      <trans-unit id="5729c34a858c78daa1aa606f62a3665527cf97e6" datatype="html">
+        <source>Do you really want to unfollow &lt;x id="INTERPOLATION" equiv-text="{{host}}"/&gt;?</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2202,22 +2202,22 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="c02051988cf0b04bc8bea7602c909c4835ed770f" datatype="html">
-        <source>You are not following &lt;x id="INTERPOLATION" equiv-text="{{ host }}"/&gt; anymore.</source>
+      <trans-unit id="fb4e35e2b0ea2abc1f71295a4b34830e57c07bd0" datatype="html">
+        <source>You are not following &lt;x id="INTERPOLATION" equiv-text="{{host}}"/&gt; anymore.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="fed7ccf455d8457dfe6b8650161b2ba991fc3162" datatype="html">
-        <source>User &lt;x id="INTERPOLATION" equiv-text="{{ username }}"/&gt; created.</source>
+      <trans-unit id="364463fab6c5714118d6449561a0f8de1cc10bfa" datatype="html">
+        <source>User &lt;x id="INTERPOLATION" equiv-text="{{username}}"/&gt; created.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="047fa00d26afadba9a3c82453e653ba863ed048b" datatype="html">
-        <source>User &lt;x id="INTERPOLATION" equiv-text="{{ username }}"/&gt; updated.</source>
+      <trans-unit id="964865a3cd90b4af99902f071644a4b2aede4c32" datatype="html">
+        <source>User &lt;x id="INTERPOLATION" equiv-text="{{username}}"/&gt; updated.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/users/user-edit/user-update.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2244,8 +2244,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="383611faadd7b4cf0bbc124d2e42b535fa6c2eb0" datatype="html">
-        <source>User &lt;x id="INTERPOLATION" equiv-text="{{ username }}"/&gt; deleted.</source>
+      <trans-unit id="28220fae6799ab98ef6b41af449aa9680082357a" datatype="html">
+        <source>User &lt;x id="INTERPOLATION" equiv-text="{{username}}"/&gt; deleted.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2258,8 +2258,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4255d5c12ab55f41866ad22453d4b70e0deab89f" datatype="html">
-        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{ name }}"/&gt; removed from the blacklist.</source>
+      <trans-unit id="1585babc36806e20e225ac27dbba0e7c7cd09e0f" datatype="html">
+        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{name}}"/&gt; removed from the blacklist.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2307,8 +2307,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="206542c1b57ce583f3cfe68b8609a0c4f791ae0c" datatype="html">
-        <source>Video channel &lt;x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/&gt; created.</source>
+      <trans-unit id="3ef8bf973a9a481a08c6f0aaa875f0259b3ea645" datatype="html">
+        <source>Video channel &lt;x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/&gt; created.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2321,15 +2321,15 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="8ad57f6504ec3c791c2fc07523053ae4bf12e63e" datatype="html">
-        <source>Video channel &lt;x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/&gt; updated.</source>
+      <trans-unit id="98ab64f0af924a60a48b40835c1b655bd17c6559" datatype="html">
+        <source>Video channel &lt;x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/&gt; updated.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cb033ad5876fce7072bceb4eeba7d2154748153f" datatype="html">
-        <source>Do you really want to delete &lt;x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/&gt;? It will delete all videos uploaded in this channel too.</source>
+      <trans-unit id="d5adc9efad0469fc3e1503d68c4ec2ff4453a814" datatype="html">
+        <source>Do you really want to delete &lt;x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/&gt;? It will delete all videos uploaded in this channel too.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2342,8 +2342,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="504b4bf7053bc5ac9853d4fd7aaa6b38703dcbd2" datatype="html">
-        <source>Video channel {{ videoChannelName } deleted.</source>
+      <trans-unit id="a81a33275b683729ad938b6102e7e34a057537a2" datatype="html">
+        <source>Video channel &lt;x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/&gt; deleted.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2356,8 +2356,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="070558f351471e268ae7a690ba31ac0c1ead6d8f" datatype="html">
-        <source>Cannot retrieve OAuth Client credentials: &lt;x id="INTERPOLATION" equiv-text="{{ errorText }}"/&gt;.
+      <trans-unit id="edeaa933b09690523e46977e11064e9c655d77d7" datatype="html">
+        <source>Cannot retrieve OAuth Client credentials: &lt;x id="INTERPOLATION" equiv-text="{{errorText}}"/&gt;.
 </source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
@@ -2406,6 +2406,387 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="b67c8e57904c67c4566610363b7f82c748d04323" datatype="html">
+        <source>Instance name is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="10a248adb1ee12830355a04ac3cde2bad2d41d7d" datatype="html">
+        <source>Short description should not be longer than 250 characters.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="356e63270712273da168072ec0fc78a969919bf1" datatype="html">
+        <source>Twitter username is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="dbb2ef02020afc05e146855f2e1dd7c9522d49b6" datatype="html">
+        <source>Previews cache size is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="97836c6e698185b4ce357de9d4b2ab3e838f2459" datatype="html">
+        <source>Previews cache size must be greater than 1.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e7393dc4a4aa12d005582eb9e1ddc7e5ca5bebd3" datatype="html">
+        <source>Previews cache size must be a number.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="2cdd5a8c604ef16c2f9a17ed81d73f4f9509e828" datatype="html">
+        <source>Signup limit is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0ca9f7ec55c9896add6e82d2b52e9217e1140cf7" datatype="html">
+        <source>Signup limit must be greater than 1.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="58c2f66ba74f1400914031ef4ed635938e9e8ced" datatype="html">
+        <source>Signup limit must be a number.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1245841647f9b42d3e7554903c1c50bdd80ab021" datatype="html">
+        <source>Admin email is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="3fd2feb77dfe57fe82573e3cdf996105e2fafc66" datatype="html">
+        <source>Admin email must be valid.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f15f2e02b1f6a96553e98ea4a969045d17ec1400" datatype="html">
+        <source>Transcoding threads is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="ba88636d27c1a6a7e1f75ff57ec182b30b851c2e" datatype="html">
+        <source>Transcoding threads must be greater than 1.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/custom-config-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5db300f6fba918a35597160183205ede13e8e149" datatype="html">
+        <source>Username is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/login-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4eb39d69b74d7a56652ec84fa6826994ee26c0e5" datatype="html">
+        <source>Password is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/login-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c90872a06666a51c2957c4b29724e68df5c67154" datatype="html">
+        <source>Confirmation of the password is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/reset-password-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="05ad6b99d9bf7b51968aa0b0b939e8627a329bea" datatype="html">
+        <source>Username must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d4b11fd0ddeea39b33f911d3aac1e82799cdaaef" datatype="html">
+        <source>Username cannot be more than 20 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5acbe0aa7a7157b1f09057a98ba01ab578a303a9" datatype="html">
+        <source>Username should be only lowercase alphanumeric characters.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="b6f52e19f074f77866fa03fabe1ddd5cdae346f0" datatype="html">
+        <source>Email is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="bef8a36c3dffff15fb5faf3d20bdbbbc1af824c1" datatype="html">
+        <source>Email must be valid.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fe26e49476ac701885abc59127e96a3760847f0" datatype="html">
+        <source>Password must be at least 6 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0a154031f3e66985af96d5f903441cf84f0dc75e" datatype="html">
+        <source>Password cannot be more than 255 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="abede840116d58f04a55d99a6cbd68da8a3e1bbf" datatype="html">
+        <source>Video quota is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="93a6dc1d3aa0d3201c86ef1ec8adf5cf0ada3c80" datatype="html">
+        <source>Quota must be greater than -1.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="545e77fd5d9526228a2133109447c23225ed9c85" datatype="html">
+        <source>User role is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1c417b7aef730d6ef5d62fa8a0a7e25e3a2393e4" datatype="html">
+        <source>Display name is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="bdeb1a8e69e137572df795d64120ea85069b7674" datatype="html">
+        <source>Display name must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e81bda510399d52f26a44a15c3dbf4d6205d90a9" datatype="html">
+        <source>Display name cannot be more than 120 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d531c2261dc0c2739bd7cbb2bb175946b7eeb3ae" datatype="html">
+        <source>Description must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="916a6e4fd83ece1dc54c6135eb3b8cd064b4bac3" datatype="html">
+        <source>Description cannot be more than 250 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/user-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="b3cf1889d2fdd6b15e697c270c9b80772fe2cae6" datatype="html">
+        <source>Report reason is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-abuse-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="993f9f5703d449a1d467243db75253d288a2947e" datatype="html">
+        <source>Report reason must be at least 2 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-abuse-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="7de2178ed1036844fb1c3ad8b7899a039fcdcdb9" datatype="html">
+        <source>Report reason cannot be more than 300 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-abuse-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fac936be125163a8494f3d7e7f21d65c7e4f1ff6" datatype="html">
+        <source>Description cannot be more than 500 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e7182e21e9566cc81c83f92727461322f71fd69b" datatype="html">
+        <source>Support text must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="3fe80c71378e127dda2dda9dbcd66b059d362813" datatype="html">
+        <source>Support text cannot be more than 500 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-channel-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="6ca60e0f6dfbc0073b0514bce7d273150b0b9e79" datatype="html">
+        <source>Comment is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-comment-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f5a94cae76685e72f33541b977efdd7845cb0ed6" datatype="html">
+        <source>Comment must be at least 2 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-comment-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="7c194080446ee6901fd17a8b8648534ffe98b123" datatype="html">
+        <source>Comment cannot be more than 3000 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-comment-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cdc51eaeab88683610a28af8645cf91d136b39e1" datatype="html">
+        <source>Video name is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c27cc734f76efd221663921dd0898ea7c8bcbb5c" datatype="html">
+        <source>Video name must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0320d0f7f8eec2341e27ca53d7875217a3d99695" datatype="html">
+        <source>Video name cannot be more than 120 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="a627c58cf1849d7d838696e7f36c1bae1a8b31a4" datatype="html">
+        <source>Video privacy is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="97afb789c1ab09074495d49aaadb92a1c3e71a16" datatype="html">
+        <source>Video channel is required.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="af5e2d5f3ac817c735fb7ff9ca16322789f66fef" datatype="html">
+        <source>Video description must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="ce28a9403c2d7e5da2e59af27118f8b6d109e906" datatype="html">
+        <source>Video description cannot be more than 10000 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f1cffdc2e156716cd9880201d65ba457d11464f8" datatype="html">
+        <source>A tag should be more than 2 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="34a0811f9a2a7366cc9efcdad52ea59b105326ea" datatype="html">
+        <source>A tag should be less than 30 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="665092574f9af9fec262f8349b67b14192391ae6" datatype="html">
+        <source>Video support must be at least 3 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e61f1c05121fa5effa6ccddf5be6dcf1c822ff4b" datatype="html">
+        <source>Video support cannot be more than 500 characters long.</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/shared/forms/form-validators/video-validators.service.ts</context>
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="0bf41abaa85526711f7952b4600e4044bc7f04a4" datatype="html">
         <source>All unsaved data will be lost, are you sure you want to leave this page?</source>
         <context-group purpose="location">
@@ -2420,78 +2801,78 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4ae5829f2615ca2343280765e6b6adfb5cc41128" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; years ago</source>
+      <trans-unit id="0b2054a863319d2cf59867addd125b6717cae41d" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; years ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a2bada0a7274e74d4318cc86d413e3ae32f57bdd" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; months ago</source>
+      <trans-unit id="e622d3813449fe36371ea258281059306819199d" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; months ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="550f8907c0a4a636d494ed945f3c10dd3a58113a" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; month ago</source>
+      <trans-unit id="2f8a5a5f7efb521d7d89dc659ff65dd13cb7b17b" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; month ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="bcc068f243c2f21112b7559f88d1d599b94e2a46" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; weeks ago</source>
+      <trans-unit id="1d1a46543a29096d3c6676be2d561380a0bc94e1" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; weeks ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a8ab22b7de1e4a70285fe7d06962a2140d5a5252" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; week ago</source>
+      <trans-unit id="e1db0b98b6cdf817508195f3649c48475c32ae7e" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; week ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="ca8bfebe411d4b56e2cfea8bd47346a7a51dea66" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; days ago</source>
+      <trans-unit id="a7654c3ece96e777527606f1c2870d6ee0b180f7" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; days ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="853e61e6ba27292056e756194829c5498387b381" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; day ago</source>
+      <trans-unit id="5b465235ae55091d32535e23dd180c407f1352d1" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; day ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="41d5a34bc1c27138d8ffbeecd7499f7854025f11" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; hours ago</source>
+      <trans-unit id="dc7addf53bd6405a9c746db6dfca665c33679a84" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; hours ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="551090bafad6b52d4677e7d65fb10692b813945b" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; hour ago</source>
+      <trans-unit id="d54a610250ed38efccf0e3afdd0004f6ad83ea8d" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; hour ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="5f751a2e17480da31cd12f8cac3e85a9a5ea9439" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; min ago</source>
+      <trans-unit id="9704e5e3adce178c127ead05f7057d3fb827308a" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; min ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a3ac5cb5be93ff145b3bf0139fe20da052060c4c" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ interval }}"/&gt; sec ago</source>
+      <trans-unit id="7a158a7555a44ea7eff9fa4988df9aa24d262ceb" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{interval}}"/&gt; sec ago</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/misc/from-now.pipe.ts</context>
           <context context-type="linenumber">1</context>
@@ -2504,8 +2885,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="3d6b54e95d42ef7586fb88f535b8d0349d431745" datatype="html">
-        <source>Too many attempts, please try again after &lt;x id="INTERPOLATION" equiv-text="{{ minutesLeft }}"/&gt; minutes.</source>
+      <trans-unit id="58546fd4d14b2d9635ce3d28c216ac68587bb25b" datatype="html">
+        <source>Too many attempts, please try again after &lt;x id="INTERPOLATION" equiv-text="{{minutesLeft}}"/&gt; minutes.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/shared/rest/rest-extractor.service.ts</context>
           <context context-type="linenumber">1</context>
@@ -2525,29 +2906,29 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="240f841426d253c459e739c19156f05d913ac10c" datatype="html">
-        <source>Registration for &lt;x id="INTERPOLATION" equiv-text="{{ username }}"/&gt; complete.</source>
+      <trans-unit id="20deec13d8d4ff199aa04318818ca44dab0585be" datatype="html">
+        <source>Registration for &lt;x id="INTERPOLATION" equiv-text="{{username}}"/&gt; complete.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/signup/signup.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cb77327761a94def3c7c0c2362e3af9e5949f57b" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ seconds }}"/&gt; of full HD videos</source>
+      <trans-unit id="10ffa5c3dbcee491d66f80d8d4dce3e119a6ec86" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{seconds}}"/&gt; of full HD videos</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/signup/signup.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="06dbb94903fc77f10c6760d7ebbb9cf649a0c8fd" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ seconds }}"/&gt; of HD videos</source>
+      <trans-unit id="344ddae9f45b344e98e7b28cd5e33243982700f8" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{seconds}}"/&gt; of HD videos</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/signup/signup.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="d44fb1f436492c547bfb99825245526958dc84e7" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ seconds }}"/&gt; of average quality videos</source>
+      <trans-unit id="435c012df6dd990a1ccb7ee73dd79c488bde28b5" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{seconds}}"/&gt; of average quality videos</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/signup/signup.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2616,8 +2997,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="36cd97a83cd16866213a1d16d1637a3639ec998f" datatype="html">
-        <source> &lt;x id="INTERPOLATION" equiv-text="{{ totalReplies }}"/&gt; replies will be deleted too.</source>
+      <trans-unit id="aeb61b334cac080733c3e03766165a346bbf42fd" datatype="html">
+        <source> &lt;x id="INTERPOLATION" equiv-text="{{totalReplies}}"/&gt; replies will be deleted too.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/videos/+video-watch/comment/video-comments.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2644,8 +3025,8 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="085d56464b75ae5c1e370f5290e4c4cf23961a61" datatype="html">
-        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{ videoName }}"/&gt; had been blacklisted.</source>
+      <trans-unit id="cafd8ec6020e69f241a107b1cb7081bd9e773d4e" datatype="html">
+        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{videoName}}"/&gt; had been blacklisted.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/videos/+video-watch/video-watch.component.ts</context>
           <context context-type="linenumber">1</context>
@@ -2658,15 +3039,15 @@ When you will upload a video in this channel, the video support field will be au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="007c1d7080cf6da1ac264b23705246f0c53e3114" datatype="html">
-        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{ videoName }}"/&gt; deleted.</source>
+      <trans-unit id="d39a0bfa616a9a8473b2e379eefe17d8ed1af118" datatype="html">
+        <source>Video &lt;x id="INTERPOLATION" equiv-text="{{videoName}}"/&gt; deleted.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/videos/+video-watch/video-watch.component.ts</context>
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cf9a064824f2fa3f01fd5544ad21032e33e60dca" datatype="html">
-        <source>&lt;x id="INTERPOLATION" equiv-text="{{ likesNumber }}"/&gt; likes / &lt;x id="INTERPOLATION_1" equiv-text="{{ dislikesNumber }}"/&gt; dislikes</source>
+      <trans-unit id="d5a4811e15319ad9354e1b62e9ca0131192b489e" datatype="html">
+        <source>&lt;x id="INTERPOLATION" equiv-text="{{likesNumber}}"/&gt; likes / &lt;x id="INTERPOLATION_1" equiv-text="{{dislikesNumber}}"/&gt; dislikes</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/videos/+video-watch/video-watch.component.ts</context>
           <context context-type="linenumber">1</context>
index 18c9f64a7f6135d620657a2edd4573617cdb2eaa..e3c052446c625fc387866ced5579b54bf130d1df 100644 (file)
@@ -630,9 +630,9 @@ Cochez cette case, sauvegardez la configuration et testez avec l'URL d'une vidé
           <context context-type="linenumber">207</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="48c189b718ed2d091e5c515bfc14b03e5ceb4f93">
-        <source>Preview cache size</source>
-        <target>Taille du cache de l'aperçu</target>
+      <trans-unit id="d00f6c2dcb426440a0a8cd8eec12d094fbfaf6f7">
+        <source>Previews cache size</source>
+        <target>Taille du cache des prévisualisations </target>
         <context-group name="null">
           <context context-type="linenumber">210</context>
         </context-group>
@@ -1117,7 +1117,7 @@ Cochez cette case, sauvegardez la configuration et testez avec l'URL d'une vidé
         <source>Display name</source>
         <target>Nom public</target>
         <context-group name="null">
-          <context context-type="linenumber">5</context>
+          <context context-type="linenumber">6</context>
         </context-group>
       </trans-unit>
       <trans-unit id="74728de5289ea2ff3f553bc2b48f1811680b931a">
@@ -1175,7 +1175,7 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
         <source>Update my profile</source>
         <target>Mettre à jour mon profil</target>
         <context-group name="null">
-          <context context-type="linenumber">23</context>
+          <context context-type="linenumber">27</context>
         </context-group>
       </trans-unit>
       <trans-unit id="e242e3e8608a3c4a944327eb3d5c221dc6e4e3cd">
@@ -1793,9 +1793,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="b0ea97653991a80d6324423949d37b8f165a4505">
-        <source>Published <x id="INTERPOLATION" equiv-text="{{ totalVideos }}"/> videos</source>
-        <target>A publié <x id="INTERPOLATION" equiv-text="{{ totalVideos }}"/> vidéos</target>
+      <trans-unit id="369ef5e9c0dd1251abdbf699a5db408bca10777f">
+        <source>Published <x id="INTERPOLATION" equiv-text="{{totalVideos}}"/> videos</source>
+        <target>A publié <x id="INTERPOLATION" equiv-text="{{totalVideos}}"/> vidéos</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1807,9 +1807,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="6b988bab9e171f65ed3510e8a66b9c5f7fcc5209">
-        <source>You set custom <x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/>. </source>
-        <target>Vous avez paramétré <x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/>. </target>
+      <trans-unit id="27a71a0aee65258179e90ecf0841c0a68f95beed">
+        <source>You set custom <x id="INTERPOLATION" equiv-text="{{customizationsText}}"/>. </source>
+        <target>Vous avez défini du <x id="INTERPOLATION" equiv-text="{{customizationsText}}"/>. </target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1828,16 +1828,16 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="03b6bae23e3f895ed8f53e3b29fad0cafc7dd002">
-        <source>Please type "I understand the <x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/> I set" to confirm.</source>
-        <target>Merci d'écrire "Je comprends avoir rentré &lt;x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/&gt;" pour confirmer votre choix.</target>
+      <trans-unit id="1ae0ab69f5c19d179282c8d882fd2f3c00e29119">
+        <source>Please type</source>
+        <target>Merci de taper</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="892eb3bbce40125f9ed1dc13078d2938b921ff53">
-        <source>I understand the <x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/> I set</source>
-        <target>Je comprends avoir rentré <x id="INTERPOLATION" equiv-text="{{ customizationsText }}"/></target>
+      <trans-unit id="75f4bb68ee4c6b282abfd9d8d32be22c6202794d">
+        <source>to confirm.</source>
+        <target>pour confirmer.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1856,9 +1856,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="511be2e1ddb087fe7a0d95654f5f72b446d3da87">
-        <source><x id="INTERPOLATION" equiv-text="{{ host }}"/> is not valid</source>
-        <target><x id="INTERPOLATION" equiv-text="{{ host }}"/> n'est pas un hôte valide</target>
+      <trans-unit id="fc5731a28a99b25c62d43333ceebb250d60aff84">
+        <source><x id="INTERPOLATION" equiv-text="{{host}}"/> is not valid</source>
+        <target><x id="INTERPOLATION" equiv-text="{{host}}"/> n'est pas valide</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1898,9 +1898,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="b1f6b95a2d83bc589955f2679de00ce70fa03594">
-        <source>Do you really want to unfollow <x id="INTERPOLATION" equiv-text="{{ host }}"/>?</source>
-        <target>Souhaitez-vous vraiment arrêter de suivre <x id="INTERPOLATION" equiv-text="{{ host }}"/> ?</target>
+      <trans-unit id="5729c34a858c78daa1aa606f62a3665527cf97e6">
+        <source>Do you really want to unfollow <x id="INTERPOLATION" equiv-text="{{host}}"/>?</source>
+        <target>Voulez-vous vraiment vous désabonner de <x id="INTERPOLATION" equiv-text="{{host}}"/> ?</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1912,23 +1912,23 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="c02051988cf0b04bc8bea7602c909c4835ed770f">
-        <source>You are not following <x id="INTERPOLATION" equiv-text="{{ host }}"/> anymore.</source>
-        <target>Vous ne suivez plus <x id="INTERPOLATION" equiv-text="{{ host }}"/>.</target>
+      <trans-unit id="fb4e35e2b0ea2abc1f71295a4b34830e57c07bd0">
+        <source>You are not following <x id="INTERPOLATION" equiv-text="{{host}}"/> anymore.</source>
+        <target>Vous n'êtes plus abonné à <x id="INTERPOLATION" equiv-text="{{host}}"/>.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="fed7ccf455d8457dfe6b8650161b2ba991fc3162">
-        <source>User <x id="INTERPOLATION" equiv-text="{{ username }}"/> created.</source>
-        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{ username }}"/> créé.</target>
+      <trans-unit id="364463fab6c5714118d6449561a0f8de1cc10bfa">
+        <source>User <x id="INTERPOLATION" equiv-text="{{username}}"/> created.</source>
+        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{username}}"/> créé.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="047fa00d26afadba9a3c82453e653ba863ed048b">
-        <source>User <x id="INTERPOLATION" equiv-text="{{ username }}"/> updated.</source>
-        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{ username }}"/> mis à jour.</target>
+      <trans-unit id="964865a3cd90b4af99902f071644a4b2aede4c32">
+        <source>User <x id="INTERPOLATION" equiv-text="{{username}}"/> updated.</source>
+        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{username}}"/> mis à jour.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1954,9 +1954,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="383611faadd7b4cf0bbc124d2e42b535fa6c2eb0">
-        <source>User <x id="INTERPOLATION" equiv-text="{{ username }}"/> deleted.</source>
-        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{ username }}"/> supprimé.</target>
+      <trans-unit id="28220fae6799ab98ef6b41af449aa9680082357a">
+        <source>User <x id="INTERPOLATION" equiv-text="{{username}}"/> deleted.</source>
+        <target>Utilisateur <x id="INTERPOLATION" equiv-text="{{username}}"/> supprimé.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -1968,9 +1968,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4255d5c12ab55f41866ad22453d4b70e0deab89f">
-        <source>Video <x id="INTERPOLATION" equiv-text="{{ name }}"/> removed from the blacklist.</source>
-        <target>La vidéo <x id="INTERPOLATION" equiv-text="{{ name }}"/> a bien été enlevée de la liste noire.</target>
+      <trans-unit id="1585babc36806e20e225ac27dbba0e7c7cd09e0f">
+        <source>Video <x id="INTERPOLATION" equiv-text="{{name}}"/> removed from the blacklist.</source>
+        <target>Vidéo <x id="INTERPOLATION" equiv-text="{{name}}"/> supprimée de la liste noire.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2017,9 +2017,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="206542c1b57ce583f3cfe68b8609a0c4f791ae0c">
-        <source>Video channel <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/> created.</source>
-        <target>Chaîne vidéo <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/> créée.</target>
+      <trans-unit id="3ef8bf973a9a481a08c6f0aaa875f0259b3ea645">
+        <source>Video channel <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> created.</source>
+        <target>Chaîne vidéo <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> créée.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2031,16 +2031,16 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="8ad57f6504ec3c791c2fc07523053ae4bf12e63e">
-        <source>Video channel <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/> updated.</source>
-        <target>Chaîne vidéo <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/> mise à jour.</target>
+      <trans-unit id="98ab64f0af924a60a48b40835c1b655bd17c6559">
+        <source>Video channel <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> updated.</source>
+        <target>Chaîne vidéo <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> mise à jour.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cb033ad5876fce7072bceb4eeba7d2154748153f">
-        <source>Do you really want to delete <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/>? It will delete all videos uploaded in this channel too.</source>
-        <target>Êtes-vous bien sûr de vouloir supprimer <x id="INTERPOLATION" equiv-text="{{ videoChannelName }}"/> ? Cette action aura aussi pour effet de supprimer toutes les vidéos ayant appartenu à cette chaîne.</target>
+      <trans-unit id="d5adc9efad0469fc3e1503d68c4ec2ff4453a814">
+        <source>Do you really want to delete <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/>? It will delete all videos uploaded in this channel too.</source>
+        <target>Voulez-vous vraiment supprimer <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> ? Ceci supprimera aussi toutes les vidéos téléversées dans cette chaîne.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2052,9 +2052,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="504b4bf7053bc5ac9853d4fd7aaa6b38703dcbd2">
-        <source>Video channel {{ videoChannelName } deleted.</source>
-        <target>Chaîne vidéo {{ videoChannelName } supprimée.</target>
+      <trans-unit id="a81a33275b683729ad938b6102e7e34a057537a2">
+        <source>Video channel <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> deleted.</source>
+        <target>Chaîne vidéo <x id="INTERPOLATION" equiv-text="{{videoChannelName}}"/> supprimée.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2066,10 +2066,10 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="070558f351471e268ae7a690ba31ac0c1ead6d8f">
-        <source>Cannot retrieve OAuth Client credentials: <x id="INTERPOLATION" equiv-text="{{ errorText }}"/>.
+      <trans-unit id="edeaa933b09690523e46977e11064e9c655d77d7">
+        <source>Cannot retrieve OAuth Client credentials: <x id="INTERPOLATION" equiv-text="{{errorText}}"/>.
 </source>
-        <target>Impossible de récupérer les identifiants Client OAuth : <x id="INTERPOLATION" equiv-text="{{ errorText }}"/>.
+        <target>Impossible de retrouver  les identifiants client OAuth : <x id="INTERPOLATION" equiv-text="{{errorText}}"/>.
 </target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
@@ -2117,6 +2117,363 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="b67c8e57904c67c4566610363b7f82c748d04323">
+        <source>Instance name is required.</source>
+        <target>Le nom de l'instance est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="10a248adb1ee12830355a04ac3cde2bad2d41d7d">
+        <source>Short description should not be longer than 250 characters.</source>
+        <target>La courte description ne peut pas faire plus de 250 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="356e63270712273da168072ec0fc78a969919bf1">
+        <source>Twitter username is required.</source>
+        <target>L'identifiant Twitter est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="dbb2ef02020afc05e146855f2e1dd7c9522d49b6">
+        <source>Previews cache size is required.</source>
+        <target>La taille du cache des prévisualisations est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="97836c6e698185b4ce357de9d4b2ab3e838f2459">
+        <source>Previews cache size must be greater than 1.</source>
+        <target>La taille du cache des prévisualisations doit être plus grand que 1.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e7393dc4a4aa12d005582eb9e1ddc7e5ca5bebd3">
+        <source>Previews cache size must be a number.</source>
+        <target>La taille du cache des prévisualisations doit être un nombre.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="2cdd5a8c604ef16c2f9a17ed81d73f4f9509e828">
+        <source>Signup limit is required.</source>
+        <target>La limite d'enregistrements est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0ca9f7ec55c9896add6e82d2b52e9217e1140cf7">
+        <source>Signup limit must be greater than 1.</source>
+        <target>La limite d'enregistrement doit faire plus de 1.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="58c2f66ba74f1400914031ef4ed635938e9e8ced">
+        <source>Signup limit must be a number.</source>
+        <target>La limite d'enregistrement doit être un nombre.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1245841647f9b42d3e7554903c1c50bdd80ab021">
+        <source>Admin email is required.</source>
+        <target>L'email de l'administrateur est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="3fd2feb77dfe57fe82573e3cdf996105e2fafc66">
+        <source>Admin email must be valid.</source>
+        <target>L'email de l'administrateur doit être valide</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f15f2e02b1f6a96553e98ea4a969045d17ec1400">
+        <source>Transcoding threads is required.</source>
+        <target>Le nombre de threads pour l'encodage est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="ba88636d27c1a6a7e1f75ff57ec182b30b851c2e">
+        <source>Transcoding threads must be greater than 1.</source>
+        <target>Le nombre de threads pour l'encodage doit être plus grand que 1.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5db300f6fba918a35597160183205ede13e8e149">
+        <source>Username is required.</source>
+        <target>Le nom d'utilisateur est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4eb39d69b74d7a56652ec84fa6826994ee26c0e5">
+        <source>Password is required.</source>
+        <target>Le mot de passe est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c90872a06666a51c2957c4b29724e68df5c67154">
+        <source>Confirmation of the password is required.</source>
+        <target>La confirmation du mot de passe est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="05ad6b99d9bf7b51968aa0b0b939e8627a329bea">
+        <source>Username must be at least 3 characters long.</source>
+        <target>Le nom d'utilisateur doit être composé d'au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d4b11fd0ddeea39b33f911d3aac1e82799cdaaef">
+        <source>Username cannot be more than 20 characters long.</source>
+        <target>Le nom d'utilisateur ne peut pas faire plus de 20 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5acbe0aa7a7157b1f09057a98ba01ab578a303a9">
+        <source>Username should be only lowercase alphanumeric characters.</source>
+        <target>Le nom d'utilisateur ne doit être composé que de caractères alphnumériques en minuscule.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="b6f52e19f074f77866fa03fabe1ddd5cdae346f0">
+        <source>Email is required.</source>
+        <target>L'email est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="bef8a36c3dffff15fb5faf3d20bdbbbc1af824c1">
+        <source>Email must be valid.</source>
+        <target>L'email doit être valide.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fe26e49476ac701885abc59127e96a3760847f0">
+        <source>Password must be at least 6 characters long.</source>
+        <target>Le mot de passe doit être composé d'au moins 6 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0a154031f3e66985af96d5f903441cf84f0dc75e">
+        <source>Password cannot be more than 255 characters long.</source>
+        <target>Le mot de passe ne peut pas faire plus de 255 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="abede840116d58f04a55d99a6cbd68da8a3e1bbf">
+        <source>Video quota is required.</source>
+        <target>Le quota de vidéos est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="93a6dc1d3aa0d3201c86ef1ec8adf5cf0ada3c80">
+        <source>Quota must be greater than -1.</source>
+        <target>Le quota doit être plus grand que -1.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="545e77fd5d9526228a2133109447c23225ed9c85">
+        <source>User role is required.</source>
+        <target>Le rôle utilisateur est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1c417b7aef730d6ef5d62fa8a0a7e25e3a2393e4">
+        <source>Display name is required.</source>
+        <target>Le nom d'affichage est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="bdeb1a8e69e137572df795d64120ea85069b7674">
+        <source>Display name must be at least 3 characters long.</source>
+        <target>Le nom d'affichage doit être composé d'au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e81bda510399d52f26a44a15c3dbf4d6205d90a9">
+        <source>Display name cannot be more than 120 characters long.</source>
+        <target>Le nom d'affichage ne peut pas faire plus de 120 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d531c2261dc0c2739bd7cbb2bb175946b7eeb3ae">
+        <source>Description must be at least 3 characters long.</source>
+        <target>La description doit être composé d'au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="916a6e4fd83ece1dc54c6135eb3b8cd064b4bac3">
+        <source>Description cannot be more than 250 characters long.</source>
+        <target>La description ne peut pas faire plus de 250 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="b3cf1889d2fdd6b15e697c270c9b80772fe2cae6">
+        <source>Report reason is required.</source>
+        <target>La raison du signalement est requise.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="993f9f5703d449a1d467243db75253d288a2947e">
+        <source>Report reason must be at least 2 characters long.</source>
+        <target>La raison du signalement doit être composé d'au moins 2 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="7de2178ed1036844fb1c3ad8b7899a039fcdcdb9">
+        <source>Report reason cannot be more than 300 characters long.</source>
+        <target>La raison du signalement ne peut pas faire plus de 300 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fac936be125163a8494f3d7e7f21d65c7e4f1ff6">
+        <source>Description cannot be more than 500 characters long.</source>
+        <target>La description ne peut pas faire plus de 500 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e7182e21e9566cc81c83f92727461322f71fd69b">
+        <source>Support text must be at least 3 characters long.</source>
+        <target>Le texte de support doit être composé d'au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="3fe80c71378e127dda2dda9dbcd66b059d362813">
+        <source>Support text cannot be more than 500 characters long.</source>
+        <target>Le texte du support ne peut pas faire plus de 500 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="6ca60e0f6dfbc0073b0514bce7d273150b0b9e79">
+        <source>Comment is required.</source>
+        <target>Le commentaire est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f5a94cae76685e72f33541b977efdd7845cb0ed6">
+        <source>Comment must be at least 2 characters long.</source>
+        <target>Le commentaire doit être composé d'au moins 2 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="7c194080446ee6901fd17a8b8648534ffe98b123">
+        <source>Comment cannot be more than 3000 characters long.</source>
+        <target>Le commentaire ne peut pas faire plus de 3000 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cdc51eaeab88683610a28af8645cf91d136b39e1">
+        <source>Video name is required.</source>
+        <target>Le nom de la vidéo est requis.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c27cc734f76efd221663921dd0898ea7c8bcbb5c">
+        <source>Video name must be at least 3 characters long.</source>
+        <target>Le nom de la vidéo doit faire au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="0320d0f7f8eec2341e27ca53d7875217a3d99695">
+        <source>Video name cannot be more than 120 characters long.</source>
+        <target>Le nom de la vidéo ne doit pas faire plus de 120 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="a627c58cf1849d7d838696e7f36c1bae1a8b31a4">
+        <source>Video privacy is required.</source>
+        <target>La confidentialité de la vidéo est requise.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="97afb789c1ab09074495d49aaadb92a1c3e71a16">
+        <source>Video channel is required.</source>
+        <target>La chaîne de la vidéo est requise.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="af5e2d5f3ac817c735fb7ff9ca16322789f66fef">
+        <source>Video description must be at least 3 characters long.</source>
+        <target>La description de la vidéo doit faire au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="ce28a9403c2d7e5da2e59af27118f8b6d109e906">
+        <source>Video description cannot be more than 10000 characters long.</source>
+        <target>La description de la vidéo ne peut pas faire plus de 10000 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="f1cffdc2e156716cd9880201d65ba457d11464f8">
+        <source>A tag should be more than 2 characters long.</source>
+        <target>Une étiquette doit faire au moins 2 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="34a0811f9a2a7366cc9efcdad52ea59b105326ea">
+        <source>A tag should be less than 30 characters long.</source>
+        <target>Une étiquette ne peut pas faire plus de 30 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="665092574f9af9fec262f8349b67b14192391ae6">
+        <source>Video support must be at least 3 characters long.</source>
+        <target>Le texte de support de la vidéo doit faire au moins 3 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="e61f1c05121fa5effa6ccddf5be6dcf1c822ff4b">
+        <source>Video support cannot be more than 500 characters long.</source>
+        <target>Le texte de support de la vidéo ne peut pas faire plus de 500 caractères.</target>
+        <context-group name="null">
+          <context context-type="linenumber">1</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="0bf41abaa85526711f7952b4600e4044bc7f04a4">
         <source>All unsaved data will be lost, are you sure you want to leave this page?</source>
         <target>Toutes les données non sauvegardées seront perdues ; êtes-vous bien sûr·e de quitter cette page ?</target>
@@ -2131,79 +2488,79 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4ae5829f2615ca2343280765e6b6adfb5cc41128">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> years ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> ans</target>
+      <trans-unit id="0b2054a863319d2cf59867addd125b6717cae41d">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> years ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> ans</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a2bada0a7274e74d4318cc86d413e3ae32f57bdd">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> months ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> mois</target>
+      <trans-unit id="e622d3813449fe36371ea258281059306819199d">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> months ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> mois</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="550f8907c0a4a636d494ed945f3c10dd3a58113a">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> month ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> mois</target>
+      <trans-unit id="2f8a5a5f7efb521d7d89dc659ff65dd13cb7b17b">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> month ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> mois</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="bcc068f243c2f21112b7559f88d1d599b94e2a46">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> weeks ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> semaines</target>
+      <trans-unit id="1d1a46543a29096d3c6676be2d561380a0bc94e1">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> weeks ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> semaines</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a8ab22b7de1e4a70285fe7d06962a2140d5a5252">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> week ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> semaines</target>
+      <trans-unit id="e1db0b98b6cdf817508195f3649c48475c32ae7e">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> week ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> semaine</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="ca8bfebe411d4b56e2cfea8bd47346a7a51dea66">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> days ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> jours</target>
+      <trans-unit id="a7654c3ece96e777527606f1c2870d6ee0b180f7">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> days ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> jours</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="853e61e6ba27292056e756194829c5498387b381">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> day ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> jour</target>
+      <trans-unit id="5b465235ae55091d32535e23dd180c407f1352d1">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> day ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> jour</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="41d5a34bc1c27138d8ffbeecd7499f7854025f11">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> hours ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> heures</target>
+      <trans-unit id="dc7addf53bd6405a9c746db6dfca665c33679a84">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> hours ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> heures</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="551090bafad6b52d4677e7d65fb10692b813945b">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> hour ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> heure</target>
+      <trans-unit id="d54a610250ed38efccf0e3afdd0004f6ad83ea8d">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> hour ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> heure</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="5f751a2e17480da31cd12f8cac3e85a9a5ea9439">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> min ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> min</target>
+      <trans-unit id="9704e5e3adce178c127ead05f7057d3fb827308a">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> min ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> min</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="a3ac5cb5be93ff145b3bf0139fe20da052060c4c">
-        <source><x id="INTERPOLATION" equiv-text="{{ interval }}"/> sec ago</source>
-        <target>il y a <x id="INTERPOLATION" equiv-text="{{ interval }}"/> sec</target>
+      <trans-unit id="7a158a7555a44ea7eff9fa4988df9aa24d262ceb">
+        <source><x id="INTERPOLATION" equiv-text="{{interval}}"/> sec ago</source>
+        <target>il y a <x id="INTERPOLATION" equiv-text="{{interval}}"/> sec</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2215,9 +2572,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="3d6b54e95d42ef7586fb88f535b8d0349d431745">
-        <source>Too many attempts, please try again after <x id="INTERPOLATION" equiv-text="{{ minutesLeft }}"/> minutes.</source>
-        <target>Trop d'essais ; merci de réitérer après <x id="INTERPOLATION" equiv-text="{{ minutesLeft }}"/> minutes.</target>
+      <trans-unit id="58546fd4d14b2d9635ce3d28c216ac68587bb25b">
+        <source>Too many attempts, please try again after <x id="INTERPOLATION" equiv-text="{{minutesLeft}}"/> minutes.</source>
+        <target>Trop de tentatives, merci de réessayer dans <x id="INTERPOLATION" equiv-text="{{minutesLeft}}"/> minutes.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2236,30 +2593,30 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="240f841426d253c459e739c19156f05d913ac10c">
-        <source>Registration for <x id="INTERPOLATION" equiv-text="{{ username }}"/> complete.</source>
-        <target>Inscription faite pour <x id="INTERPOLATION" equiv-text="{{ username }}"/>.</target>
+      <trans-unit id="20deec13d8d4ff199aa04318818ca44dab0585be">
+        <source>Registration for <x id="INTERPOLATION" equiv-text="{{username}}"/> complete.</source>
+        <target>Enregistrement pour <x id="INTERPOLATION" equiv-text="{{username}}"/> complété.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cb77327761a94def3c7c0c2362e3af9e5949f57b">
-        <source><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> of full HD videos</source>
-        <target><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> de vidéos en Full HD</target>
+      <trans-unit id="10ffa5c3dbcee491d66f80d8d4dce3e119a6ec86">
+        <source><x id="INTERPOLATION" equiv-text="{{seconds}}"/> of full HD videos</source>
+        <target><x id="INTERPOLATION" equiv-text="{{seconds}}"/> de vidéos full HD</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="06dbb94903fc77f10c6760d7ebbb9cf649a0c8fd">
-        <source><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> of HD videos</source>
-        <target><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> de vidéos en HD</target>
+      <trans-unit id="344ddae9f45b344e98e7b28cd5e33243982700f8">
+        <source><x id="INTERPOLATION" equiv-text="{{seconds}}"/> of HD videos</source>
+        <target><x id="INTERPOLATION" equiv-text="{{seconds}}"/> de vidéos HD</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="d44fb1f436492c547bfb99825245526958dc84e7">
-        <source><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> of average quality videos</source>
-        <target><x id="INTERPOLATION" equiv-text="{{ seconds }}"/> de vidéos de qualité moyenne</target>
+      <trans-unit id="435c012df6dd990a1ccb7ee73dd79c488bde28b5">
+        <source><x id="INTERPOLATION" equiv-text="{{seconds}}"/> of average quality videos</source>
+        <target><x id="INTERPOLATION" equiv-text="{{seconds}}"/> de vidéos de qualité moyenne</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2327,9 +2684,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="36cd97a83cd16866213a1d16d1637a3639ec998f">
-        <source> <x id="INTERPOLATION" equiv-text="{{ totalReplies }}"/> replies will be deleted too.</source>
-        <target> <x id="INTERPOLATION" equiv-text="{{ totalReplies }}"/> commentaires seront aussi supprimés.</target>
+      <trans-unit id="aeb61b334cac080733c3e03766165a346bbf42fd">
+        <source> <x id="INTERPOLATION" equiv-text="{{totalReplies}}"/> replies will be deleted too.</source>
+        <target> <x id="INTERPOLATION" equiv-text="{{totalReplies}}"/> réponses seront aussi supprimées.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2355,9 +2712,9 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="085d56464b75ae5c1e370f5290e4c4cf23961a61">
-        <source>Video <x id="INTERPOLATION" equiv-text="{{ videoName }}"/> had been blacklisted.</source>
-        <target>La vidéo <x id="INTERPOLATION" equiv-text="{{ videoName }}"/> a bien été mise sur liste noire.</target>
+      <trans-unit id="cafd8ec6020e69f241a107b1cb7081bd9e773d4e">
+        <source>Video <x id="INTERPOLATION" equiv-text="{{videoName}}"/> had been blacklisted.</source>
+        <target>La vidéo <x id="INTERPOLATION" equiv-text="{{videoName}}"/> a été mise sur liste noire.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
@@ -2369,16 +2726,16 @@ Quand vous mettrez en ligne une vidéo sur cette chaîne, la vidéo affichera au
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="007c1d7080cf6da1ac264b23705246f0c53e3114">
-        <source>Video <x id="INTERPOLATION" equiv-text="{{ videoName }}"/> deleted.</source>
-        <target>La vidéo <x id="INTERPOLATION" equiv-text="{{ videoName }}"/> a été supprimée.</target>
+      <trans-unit id="d39a0bfa616a9a8473b2e379eefe17d8ed1af118">
+        <source>Video <x id="INTERPOLATION" equiv-text="{{videoName}}"/> deleted.</source>
+        <target>La vidéo <x id="INTERPOLATION" equiv-text="{{videoName}}"/> a été supprimée.</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="cf9a064824f2fa3f01fd5544ad21032e33e60dca">
-        <source><x id="INTERPOLATION" equiv-text="{{ likesNumber }}"/> likes / <x id="INTERPOLATION_1" equiv-text="{{ dislikesNumber }}"/> dislikes</source>
-        <target><x id="INTERPOLATION" equiv-text="{{ likesNumber }}"/> likes / <x id="INTERPOLATION_1" equiv-text="{{ dislikesNumber }}"/> dislikes</target>
+      <trans-unit id="d5a4811e15319ad9354e1b62e9ca0131192b489e">
+        <source><x id="INTERPOLATION" equiv-text="{{likesNumber}}"/> likes / <x id="INTERPOLATION_1" equiv-text="{{dislikesNumber}}"/> dislikes</source>
+        <target><x id="INTERPOLATION" equiv-text="{{likesNumber}}"/> j'aime / <x id="INTERPOLATION_1" equiv-text="{{dislikesNumber}}"/> je n'aime pas</target>
         <context-group name="null">
           <context context-type="linenumber">1</context>
         </context-group>
index e1a69e4a4b55a5d86ba5bd3fdb77da19c51ed49a..85c4c0672a0929a9e253f98319992c126b1c66c8 100644 (file)
@@ -1,4 +1,4 @@
-import { enableProdMode } from '@angular/core'
+import { enableProdMode, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core'
 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
 
 import { AppModule } from './app/app.module'
@@ -6,12 +6,22 @@ import { environment } from './environments/environment'
 
 import { hmrBootstrap } from './hmr'
 
+let providers = []
 if (environment.production) {
   enableProdMode()
 }
 
+if (environment.production === false && window.location.search === '?lang=fr') {
+  const translations = require(`raw-loader!./locale/target/messages_fr.xml`)
+
+  providers = [
+    { provide: TRANSLATIONS, useValue: translations },
+    { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }
+  ]
+}
+
 const bootstrap = () => platformBrowserDynamic()
-  .bootstrapModule(AppModule)
+  .bootstrapModule(AppModule, { providers })
   .then(bootstrapModule => {
     // TODO: Uncomment and remove unregistration when https://github.com/angular/angular/issues/21191 is fixed
     // TODO: Remove when https://github.com/angular/angular-cli/issues/8779 is fixed?