aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+admin
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/+admin')
-rw-r--r--client/src/app/+admin/admin.component.html12
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html140
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts28
-rw-r--r--client/src/app/+admin/follows/followers-list/followers-list.component.html12
-rw-r--r--client/src/app/+admin/follows/followers-list/followers-list.component.ts6
-rw-r--r--client/src/app/+admin/follows/following-add/following-add.component.html6
-rw-r--r--client/src/app/+admin/follows/following-add/following-add.component.ts22
-rw-r--r--client/src/app/+admin/follows/following-list/following-list.component.html8
-rw-r--r--client/src/app/+admin/follows/following-list/following-list.component.ts18
-rw-r--r--client/src/app/+admin/follows/follows.component.html2
-rw-r--r--client/src/app/+admin/jobs/index.ts5
-rw-r--r--client/src/app/+admin/jobs/jobs-list/jobs-list.component.html12
-rw-r--r--client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts6
-rw-r--r--client/src/app/+admin/users/shared/user.service.ts7
-rw-r--r--client/src/app/+admin/users/user-edit/user-create.component.ts21
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.component.html20
-rw-r--r--client/src/app/+admin/users/user-edit/user-update.component.ts11
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html14
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts19
-rw-r--r--client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html14
-rw-r--r--client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts6
-rw-r--r--client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html16
-rw-r--r--client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts23
23 files changed, 240 insertions, 188 deletions
diff --git a/client/src/app/+admin/admin.component.html b/client/src/app/+admin/admin.component.html
index e4644498b..1b2b89c3a 100644
--- a/client/src/app/+admin/admin.component.html
+++ b/client/src/app/+admin/admin.component.html
@@ -1,26 +1,26 @@
1<div class="row"> 1<div class="row">
2 <div class="sub-menu"> 2 <div class="sub-menu">
3 <a *ngIf="hasUsersRight()" routerLink="/admin/users" routerLinkActive="active" class="title-page"> 3 <a i18n *ngIf="hasUsersRight()" routerLink="/admin/users" routerLinkActive="active" class="title-page">
4 Users 4 Users
5 </a> 5 </a>
6 6
7 <a *ngIf="hasServerFollowRight()" routerLink="/admin/follows" routerLinkActive="active" class="title-page"> 7 <a i18n *ngIf="hasServerFollowRight()" routerLink="/admin/follows" routerLinkActive="active" class="title-page">
8 Manage follows 8 Manage follows
9 </a> 9 </a>
10 10
11 <a *ngIf="hasVideoAbusesRight()" routerLink="/admin/video-abuses" routerLinkActive="active" class="title-page"> 11 <a i18n *ngIf="hasVideoAbusesRight()" routerLink="/admin/video-abuses" routerLinkActive="active" class="title-page">
12 Video abuses 12 Video abuses
13 </a> 13 </a>
14 14
15 <a *ngIf="hasVideoBlacklistRight()" routerLink="/admin/video-blacklist" routerLinkActive="active" class="title-page"> 15 <a i18n *ngIf="hasVideoBlacklistRight()" routerLink="/admin/video-blacklist" routerLinkActive="active" class="title-page">
16 Video blacklist 16 Video blacklist
17 </a> 17 </a>
18 18
19 <a *ngIf="hasJobsRight()" routerLink="/admin/jobs" routerLinkActive="active" class="title-page"> 19 <a i18n *ngIf="hasJobsRight()" routerLink="/admin/jobs" routerLinkActive="active" class="title-page">
20 Jobs 20 Jobs
21 </a> 21 </a>
22 22
23 <a *ngIf="hasConfigRight()" routerLink="/admin/config" routerLinkActive="active" class="title-page"> 23 <a i18n *ngIf="hasConfigRight()" routerLink="/admin/config" routerLinkActive="active" class="title-page">
24 Configuration 24 Configuration
25 </a> 25 </a>
26 </div> 26 </div>
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index 8a1e33c56..4263b7b5f 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -4,13 +4,13 @@
4 4
5 <tab heading="Basic configuration"> 5 <tab heading="Basic configuration">
6 6
7 <div class="inner-form-title">Instance</div> 7 <div i18n class="inner-form-title">Instance</div>
8 8
9 <div class="form-group"> 9 <div class="form-group">
10 <label for="instanceName">Name</label> 10 <label i18n for="instanceName">Name</label>
11 <input 11 <input
12 type="text" id="instanceName" 12 type="text" id="instanceName"
13 formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }" 13 formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
14 > 14 >
15 <div *ngIf="formErrors.instanceName" class="form-error"> 15 <div *ngIf="formErrors.instanceName" class="form-error">
16 {{ formErrors.instanceName }} 16 {{ formErrors.instanceName }}
@@ -18,10 +18,10 @@
18 </div> 18 </div>
19 19
20 <div class="form-group"> 20 <div class="form-group">
21 <label for="instanceShortDescription">Short description</label> 21 <label i18n for="instanceShortDescription">Short description</label>
22 <textarea 22 <textarea
23 id="instanceShortDescription" formControlName="instanceShortDescription" 23 id="instanceShortDescription" formControlName="instanceShortDescription"
24 [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }" 24 [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
25 ></textarea> 25 ></textarea>
26 <div *ngIf="formErrors.instanceShortDescription" class="form-error"> 26 <div *ngIf="formErrors.instanceShortDescription" class="form-error">
27 {{ formErrors.instanceShortDescription }} 27 {{ formErrors.instanceShortDescription }}
@@ -29,10 +29,10 @@
29 </div> 29 </div>
30 30
31 <div class="form-group"> 31 <div class="form-group">
32 <label for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help> 32 <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
33 <my-markdown-textarea 33 <my-markdown-textarea
34 id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true" 34 id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
35 [classes]="{ 'input-error': formErrors['instanceDescription'] }" 35 [classes]="{ 'input-error': formErrors['instanceDescription'] }"
36 ></my-markdown-textarea> 36 ></my-markdown-textarea>
37 <div *ngIf="formErrors.instanceDescription" class="form-error"> 37 <div *ngIf="formErrors.instanceDescription" class="form-error">
38 {{ formErrors.instanceDescription }} 38 {{ formErrors.instanceDescription }}
@@ -40,10 +40,10 @@
40 </div> 40 </div>
41 41
42 <div class="form-group"> 42 <div class="form-group">
43 <label for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help> 43 <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
44 <my-markdown-textarea 44 <my-markdown-textarea
45 id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true" 45 id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
46 [ngClass]="{ 'input-error': formErrors['instanceTerms'] }" 46 [ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
47 ></my-markdown-textarea> 47 ></my-markdown-textarea>
48 <div *ngIf="formErrors.instanceTerms" class="form-error"> 48 <div *ngIf="formErrors.instanceTerms" class="form-error">
49 {{ formErrors.instanceTerms }} 49 {{ formErrors.instanceTerms }}
@@ -51,12 +51,12 @@
51 </div> 51 </div>
52 52
53 <div class="form-group"> 53 <div class="form-group">
54 <label for="instanceDefaultClientRoute">Default client route</label> 54 <label i18n for="instanceDefaultClientRoute">Default client route</label>
55 <div class="peertube-select-container"> 55 <div class="peertube-select-container">
56 <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute"> 56 <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
57 <option value="/videos/trending">Videos Trending</option> 57 <option i18n value="/videos/trending">Videos Trending</option>
58 <option value="/videos/recently-added">Videos Recently Added</option> 58 <option i18n value="/videos/recently-added">Videos Recently Added</option>
59 <option value="/videos/local">Local videos</option> 59 <option i18n value="/videos/local">Local videos</option>
60 </select> 60 </select>
61 </div> 61 </div>
62 <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error"> 62 <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
@@ -65,14 +65,17 @@
65 </div> 65 </div>
66 66
67 <div class="form-group"> 67 <div class="form-group">
68 <label for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label> 68 <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
69 <my-help helpType="custom" customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."></my-help> 69 <my-help
70 helpType="custom" i18n-customHtml
71 customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."
72 ></my-help>
70 73
71 <div class="peertube-select-container"> 74 <div class="peertube-select-container">
72 <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy"> 75 <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
73 <option value="do_not_list">Do not list</option> 76 <option i18n value="do_not_list">Do not list</option>
74 <option value="blur">Blur thumbnails</option> 77 <option i18n value="blur">Blur thumbnails</option>
75 <option value="display">Display</option> 78 <option i18n value="display">Display</option>
76 </select> 79 </select>
77 </div> 80 </div>
78 <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error"> 81 <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
@@ -80,43 +83,43 @@
80 </div> 83 </div>
81 </div> 84 </div>
82 85
83 <div class="inner-form-title">Signup</div> 86 <div i18n class="inner-form-title">Signup</div>
84 87
85 <div class="form-group"> 88 <div class="form-group">
86 <input type="checkbox" id="signupEnabled" formControlName="signupEnabled"> 89 <input type="checkbox" id="signupEnabled" formControlName="signupEnabled">
87 90
88 <label for="signupEnabled"></label> 91 <label for="signupEnabled"></label>
89 <label for="signupEnabled">Signup enabled</label> 92 <label i18n for="signupEnabled">Signup enabled</label>
90 </div> 93 </div>
91 94
92 <div *ngIf="isSignupEnabled()" class="form-group"> 95 <div *ngIf="isSignupEnabled()" class="form-group">
93 <label for="signupLimit">Signup limit</label> 96 <label i18n for="signupLimit">Signup limit</label>
94 <input 97 <input
95 type="text" id="signupLimit" 98 type="text" id="signupLimit"
96 formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }" 99 formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }"
97 > 100 >
98 <div *ngIf="formErrors.signupLimit" class="form-error"> 101 <div *ngIf="formErrors.signupLimit" class="form-error">
99 {{ formErrors.signupLimit }} 102 {{ formErrors.signupLimit }}
100 </div> 103 </div>
101 </div> 104 </div>
102 105
103 <div class="inner-form-title">Administrator</div> 106 <div i18n class="inner-form-title">Administrator</div>
104 107
105 <div class="form-group"> 108 <div class="form-group">
106 <label for="adminEmail">Admin email</label> 109 <label i18n for="adminEmail">Admin email</label>
107 <input 110 <input
108 type="text" id="adminEmail" 111 type="text" id="adminEmail"
109 formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }" 112 formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }"
110 > 113 >
111 <div *ngIf="formErrors.adminEmail" class="form-error"> 114 <div *ngIf="formErrors.adminEmail" class="form-error">
112 {{ formErrors.adminEmail }} 115 {{ formErrors.adminEmail }}
113 </div> 116 </div>
114 </div> 117 </div>
115 118
116 <div class="inner-form-title">Users</div> 119 <div i18n class="inner-form-title">Users</div>
117 120
118 <div class="form-group"> 121 <div class="form-group">
119 <label for="userVideoQuota">User default video quota</label> 122 <label i18n for="userVideoQuota">User default video quota</label>
120 <div class="peertube-select-container"> 123 <div class="peertube-select-container">
121 <select id="userVideoQuota" formControlName="userVideoQuota"> 124 <select id="userVideoQuota" formControlName="userVideoQuota">
122 <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value"> 125 <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
@@ -132,14 +135,17 @@
132 135
133 <tab heading="Services"> 136 <tab heading="Services">
134 137
135 <div class="inner-form-title">Twitter</div> 138 <div i18n class="inner-form-title">Twitter</div>
136 139
137 <div class="form-group"> 140 <div class="form-group">
138 <label for="signupLimit">Your Twitter username</label> 141 <label i18n for="signupLimit">Your Twitter username</label>
139 <my-help helpType="custom" customHtml="Indicates the Twitter account for the website or platform on which the content was published."></my-help> 142 <my-help
143 helpType="custom" i18n-customHtml
144 customHtml="Indicates the Twitter account for the website or platform on which the content was published."
145 ></my-help>
140 <input 146 <input
141 type="text" id="servicesTwitterUsername" 147 type="text" id="servicesTwitterUsername"
142 formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }" 148 formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }"
143 > 149 >
144 <div *ngIf="formErrors.servicesTwitterUsername" class="form-error"> 150 <div *ngIf="formErrors.servicesTwitterUsername" class="form-error">
145 {{ formErrors.servicesTwitterUsername }} 151 {{ formErrors.servicesTwitterUsername }}
@@ -150,29 +156,32 @@
150 <input type="checkbox" id="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted"> 156 <input type="checkbox" id="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted">
151 157
152 <label for="servicesTwitterWhitelisted"></label> 158 <label for="servicesTwitterWhitelisted"></label>
153 <label for="servicesTwitterWhitelisted">Instance whitelisted by Twitter</label> 159 <label i18n for="servicesTwitterWhitelisted">Instance whitelisted by Twitter</label>
154 <my-help helpType="custom" customHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br /> 160 <my-help
161 helpType="custom" i18n-customHtml
162 customHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
155If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br /> 163If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
156Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."></my-help> 164Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."
165 ></my-help>
157 166
158 </div> 167 </div>
159 </tab> 168 </tab>
160 169
161 <tab heading="Advanced configuration"> 170 <tab heading="Advanced configuration">
162 171
163 <div class="inner-form-title">Transcoding</div> 172 <div i18n class="inner-form-title">Transcoding</div>
164 173
165 <div class="form-group"> 174 <div class="form-group">
166 <input type="checkbox" id="transcodingEnabled" formControlName="transcodingEnabled"> 175 <input type="checkbox" id="transcodingEnabled" formControlName="transcodingEnabled">
167 176
168 <label for="transcodingEnabled"></label> 177 <label for="transcodingEnabled"></label>
169 <label for="transcodingEnabled">Transcoding enabled</label> 178 <label i18n for="transcodingEnabled">Transcoding enabled</label>
170 </div> 179 </div>
171 180
172 <ng-template [ngIf]="isTranscodingEnabled()"> 181 <ng-template [ngIf]="isTranscodingEnabled()">
173 182
174 <div class="form-group"> 183 <div class="form-group">
175 <label for="transcodingThreads">Transcoding threads</label> 184 <label i18n for="transcodingThreads">Transcoding threads</label>
176 <div class="peertube-select-container"> 185 <div class="peertube-select-container">
177 <select id="transcodingThreads" formControlName="transcodingThreads"> 186 <select id="transcodingThreads" formControlName="transcodingThreads">
178 <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value"> 187 <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
@@ -191,33 +200,39 @@ Check this checkbox, save the configuration and test with a video URL of your in
191 [formControlName]="getResolutionKey(resolution)" 200 [formControlName]="getResolutionKey(resolution)"
192 > 201 >
193 <label [for]="getResolutionKey(resolution)"></label> 202 <label [for]="getResolutionKey(resolution)"></label>
194 <label [for]="getResolutionKey(resolution)">Resolution {{ resolution }} enabled</label> 203 <label i18n [for]="getResolutionKey(resolution)">Resolution {{ resolution }} enabled</label>
195 </div> 204 </div>
196 </ng-template> 205 </ng-template>
197 206
198 <div class="inner-form-title">Cache</div> 207 <div i18n class="inner-form-title">Cache</div>
199 208
200 <div class="form-group"> 209 <div class="form-group">
201 <label for="cachePreviewsSize">Preview cache size</label> 210 <label i18n for="cachePreviewsSize">Preview cache size</label>
202 <my-help helpType="custom" customHtml="Previews are not federated. We fetch them directly from the origin instance and cache them."></my-help> 211 <my-help
212 helpType="custom" i18n-customHtml
213 customHtml="Previews are not federated. We fetch them directly from the origin instance and cache them."
214 ></my-help>
203 215
204 <input 216 <input
205 type="text" id="cachePreviewsSize" 217 type="text" id="cachePreviewsSize"
206 formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }" 218 formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
207 > 219 >
208 <div *ngIf="formErrors.cachePreviewsSize" class="form-error"> 220 <div *ngIf="formErrors.cachePreviewsSize" class="form-error">
209 {{ formErrors.cachePreviewsSize }} 221 {{ formErrors.cachePreviewsSize }}
210 </div> 222 </div>
211 </div> 223 </div>
212 224
213 <div class="inner-form-title">Customizations</div> 225 <div i18n class="inner-form-title">Customizations</div>
214 226
215 <div class="form-group"> 227 <div class="form-group">
216 <label for="customizationJavascript">JavaScript</label> 228 <label i18n for="customizationJavascript">JavaScript</label>
217 <my-help helpType="custom" customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"></my-help> 229 <my-help
230 helpType="custom" i18n-customHtml
231 customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
232 ></my-help>
218 <textarea 233 <textarea
219 id="customizationJavascript" formControlName="customizationJavascript" 234 id="customizationJavascript" formControlName="customizationJavascript"
220 [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }" 235 [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
221 ></textarea> 236 ></textarea>
222 <div *ngIf="formErrors.customizationJavascript" class="form-error"> 237 <div *ngIf="formErrors.customizationJavascript" class="form-error">
223 {{ formErrors.customizationJavascript }} 238 {{ formErrors.customizationJavascript }}
@@ -228,25 +243,26 @@ Check this checkbox, save the configuration and test with a video URL of your in
228 <label for="customizationCSS">CSS</label> 243 <label for="customizationCSS">CSS</label>
229 <my-help 244 <my-help
230 helpType="custom" 245 helpType="custom"
246 i18n-customHtml
231 customHtml=" 247 customHtml="
232 Write directly CSS code. Example:<br /> 248 Write directly CSS code. Example:<br />
233 <pre> 249 <pre>
234 body { 250 body {{ '{' }}
235 background-color: red; 251 background-color: red;
236 } 252 {{ '}' }}
237 </pre> 253 </pre>
238 254
239 Prepend with <em>#custom-css</em> to override styles. Example: 255 Prepend with <em>#custom-css</em> to override styles. Example:
240 <pre> 256 <pre>
241 #custom-css .logged-in-email { 257 #custom-css .logged-in-email {{ '{' }}
242 color: red; 258 color: red;
243 } 259 {{ '}' }}
244 </pre> 260 </pre>
245 " 261 "
246 ></my-help> 262 ></my-help>
247 <textarea 263 <textarea
248 id="customizationCSS" formControlName="customizationCSS" 264 id="customizationCSS" formControlName="customizationCSS"
249 [ngClass]="{ 'input-error': formErrors['customizationCSS'] }" 265 [ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
250 ></textarea> 266 ></textarea>
251 <div *ngIf="formErrors.customizationCSS" class="form-error"> 267 <div *ngIf="formErrors.customizationCSS" class="form-error">
252 {{ formErrors.customizationCSS }} 268 {{ formErrors.customizationCSS }}
@@ -255,5 +271,5 @@ Check this checkbox, save the configuration and test with a video URL of your in
255 </tab> 271 </tab>
256 </tabset> 272 </tabset>
257 273
258 <input (click)="formValidated()" type="submit" value="Update configuration" [disabled]="!form.valid"> 274 <input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid">
259</form> 275</form>
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index a1e334a74..3f9205460 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -8,12 +8,15 @@ import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared'
8import { 8import {
9 ADMIN_EMAIL, 9 ADMIN_EMAIL,
10 CACHE_PREVIEWS_SIZE, 10 CACHE_PREVIEWS_SIZE,
11 INSTANCE_NAME, INSTANCE_SHORT_DESCRIPTION, SERVICES_TWITTER_USERNAME, 11 INSTANCE_NAME,
12 INSTANCE_SHORT_DESCRIPTION,
13 SERVICES_TWITTER_USERNAME,
12 SIGNUP_LIMIT, 14 SIGNUP_LIMIT,
13 TRANSCODING_THREADS 15 TRANSCODING_THREADS
14} from '@app/shared/forms/form-validators/custom-config' 16} from '@app/shared/forms/form-validators/custom-config'
15import { NotificationsService } from 'angular2-notifications' 17import { NotificationsService } from 'angular2-notifications'
16import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model' 18import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
19import { I18n } from '@ngx-translate/i18n-polyfill'
17 20
18@Component({ 21@Component({
19 selector: 'my-edit-custom-config', 22 selector: 'my-edit-custom-config',
@@ -77,7 +80,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
77 private notificationsService: NotificationsService, 80 private notificationsService: NotificationsService,
78 private configService: ConfigService, 81 private configService: ConfigService,
79 private serverService: ServerService, 82 private serverService: ServerService,
80 private confirmService: ConfirmService 83 private confirmService: ConfirmService,
84 private i18n: I18n
81 ) { 85 ) {
82 super() 86 super()
83 } 87 }
@@ -133,7 +137,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
133 this.forceCheck() 137 this.forceCheck()
134 }, 138 },
135 139
136 err => this.notificationsService.error('Error', err.message) 140 err => this.notificationsService.error(this.i18n('Error'), err.message)
137 ) 141 )
138 } 142 }
139 143
@@ -156,11 +160,15 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
156 if (customizations.length !== 0) { 160 if (customizations.length !== 0) {
157 const customizationsText = customizations.join('/') 161 const customizationsText = customizations.join('/')
158 162
159 const message = `You set custom ${customizationsText}. ` + 163 // FIXME: i18n service does not support string concatenation
160 'This could lead to security issues or bugs if you do not understand it. ' + 164 const message = this.i18n('You set custom {{ customizationsText }}. ', { customizationsText }) +
161 'Are you sure you want to update the configuration?' 165 this.i18n('This could lead to security issues or bugs if you do not understand it. ') +
162 const label = `Please type "I understand the ${customizationsText} I set" to confirm.` 166 this.i18n('Are you sure you want to update the configuration?')
163 const expectedInputValue = `I understand the ${customizationsText} I set` 167 const label = this.i18n(
168 'Please type "I understand the {{ customizationsText }} I set" to confirm.',
169 { customizationsText }
170 )
171 const expectedInputValue = this.i18n('I understand the {{ customizationsText }} I set', { customizationsText})
164 172
165 const confirmRes = await this.confirmService.confirmWithInput(message, label, expectedInputValue) 173 const confirmRes = await this.confirmService.confirmWithInput(message, label, expectedInputValue)
166 if (confirmRes === false) return 174 if (confirmRes === false) return
@@ -223,10 +231,10 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
223 231
224 this.updateForm() 232 this.updateForm()
225 233
226 this.notificationsService.success('Success', 'Configuration updated.') 234 this.notificationsService.success(this.i18n('Success'), this.i18n('Configuration updated.'))
227 }, 235 },
228 236
229 err => this.notificationsService.error('Error', err.message) 237 err => this.notificationsService.error(this.i18n('Error'), err.message)
230 ) 238 )
231 } 239 }
232 240
diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.html b/client/src/app/+admin/follows/followers-list/followers-list.component.html
index 85d2a2cf6..1a6ed616a 100644
--- a/client/src/app/+admin/follows/followers-list/followers-list.component.html
+++ b/client/src/app/+admin/follows/followers-list/followers-list.component.html
@@ -4,12 +4,12 @@
4> 4>
5 <ng-template pTemplate="header"> 5 <ng-template pTemplate="header">
6 <tr> 6 <tr>
7 <th style="width: 60px">ID</th> 7 <th i18n style="width: 60px">ID</th>
8 <th>Score</th> 8 <th i18n>Score</th>
9 <th>Name</th> 9 <th i18n>Name</th>
10 <th>Host</th> 10 <th i18n>Host</th>
11 <th>State</th> 11 <th i18n>State</th>
12 <th pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 12 <th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
13 </tr> 13 </tr>
14 </ng-template> 14 </ng-template>
15 15
diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.ts b/client/src/app/+admin/follows/followers-list/followers-list.component.ts
index 69b3e5e58..96fb67588 100644
--- a/client/src/app/+admin/follows/followers-list/followers-list.component.ts
+++ b/client/src/app/+admin/follows/followers-list/followers-list.component.ts
@@ -5,6 +5,7 @@ import { SortMeta } from 'primeng/primeng'
5import { AccountFollow } from '../../../../../../shared/models/actors/follow.model' 5import { AccountFollow } from '../../../../../../shared/models/actors/follow.model'
6import { RestPagination, RestTable } from '../../../shared' 6import { RestPagination, RestTable } from '../../../shared'
7import { FollowService } from '../shared' 7import { FollowService } from '../shared'
8import { I18n } from '@ngx-translate/i18n-polyfill'
8 9
9@Component({ 10@Component({
10 selector: 'my-followers-list', 11 selector: 'my-followers-list',
@@ -20,7 +21,8 @@ export class FollowersListComponent extends RestTable implements OnInit {
20 21
21 constructor ( 22 constructor (
22 private notificationsService: NotificationsService, 23 private notificationsService: NotificationsService,
23 private followService: FollowService 24 private followService: FollowService,
25 private i18n: I18n
24 ) { 26 ) {
25 super() 27 super()
26 } 28 }
@@ -37,7 +39,7 @@ export class FollowersListComponent extends RestTable implements OnInit {
37 this.totalRecords = resultList.total 39 this.totalRecords = resultList.total
38 }, 40 },
39 41
40 err => this.notificationsService.error('Error', err.message) 42 err => this.notificationsService.error(this.i18n('Error'), err.message)
41 ) 43 )
42 } 44 }
43} 45}
diff --git a/client/src/app/+admin/follows/following-add/following-add.component.html b/client/src/app/+admin/follows/following-add/following-add.component.html
index 25bab9d0d..72635048c 100644
--- a/client/src/app/+admin/follows/following-add/following-add.component.html
+++ b/client/src/app/+admin/follows/following-add/following-add.component.html
@@ -2,7 +2,7 @@
2 2
3<form (ngSubmit)="addFollowing()"> 3<form (ngSubmit)="addFollowing()">
4 <div class="form-group"> 4 <div class="form-group">
5 <label for="hosts">1 host (without "http://") per line</label> 5 <label i18n for="hosts">1 host (without "http://") per line</label>
6 6
7 <textarea 7 <textarea
8 type="text" class="form-control" placeholder="example.com" id="hosts" name="hosts" 8 type="text" class="form-control" placeholder="example.com" id="hosts" name="hosts"
@@ -14,9 +14,9 @@
14 </div> 14 </div>
15 </div> 15 </div>
16 16
17 <div *ngIf="httpEnabled() === false" class="alert alert-warning"> 17 <div i18n *ngIf="httpEnabled() === false" class="alert alert-warning">
18 It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers. 18 It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
19 </div> 19 </div>
20 20
21 <input type="submit" value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-default"> 21 <input type="submit" i18n-value value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-default">
22</form> 22</form>
diff --git a/client/src/app/+admin/follows/following-add/following-add.component.ts b/client/src/app/+admin/follows/following-add/following-add.component.ts
index c296c8852..f197c1fe9 100644
--- a/client/src/app/+admin/follows/following-add/following-add.component.ts
+++ b/client/src/app/+admin/follows/following-add/following-add.component.ts
@@ -4,6 +4,7 @@ import { NotificationsService } from 'angular2-notifications'
4import { ConfirmService } from '../../../core' 4import { ConfirmService } from '../../../core'
5import { validateHost } from '../../../shared' 5import { validateHost } from '../../../shared'
6import { FollowService } from '../shared' 6import { FollowService } from '../shared'
7import { I18n } from '@ngx-translate/i18n-polyfill'
7 8
8@Component({ 9@Component({
9 selector: 'my-following-add', 10 selector: 'my-following-add',
@@ -19,7 +20,8 @@ export class FollowingAddComponent {
19 private router: Router, 20 private router: Router,
20 private notificationsService: NotificationsService, 21 private notificationsService: NotificationsService,
21 private confirmService: ConfirmService, 22 private confirmService: ConfirmService,
22 private followService: FollowService 23 private followService: FollowService,
24 private i18n: I18n
23 ) {} 25 ) {}
24 26
25 httpEnabled () { 27 httpEnabled () {
@@ -34,7 +36,7 @@ export class FollowingAddComponent {
34 36
35 for (const host of hosts) { 37 for (const host of hosts) {
36 if (validateHost(host) === false) { 38 if (validateHost(host) === false) {
37 newHostsErrors.push(`${host} is not valid`) 39 newHostsErrors.push(this.i18n('{{ host }} is not valid', { host }))
38 } 40 }
39 } 41 }
40 42
@@ -48,26 +50,26 @@ export class FollowingAddComponent {
48 50
49 const hosts = this.getNotEmptyHosts() 51 const hosts = this.getNotEmptyHosts()
50 if (hosts.length === 0) { 52 if (hosts.length === 0) {
51 this.error = 'You need to specify hosts to follow.' 53 this.error = this.i18n('You need to specify hosts to follow.')
52 } 54 }
53 55
54 if (!this.isHostsUnique(hosts)) { 56 if (!this.isHostsUnique(hosts)) {
55 this.error = 'Hosts need to be unique.' 57 this.error = this.i18n('Hosts need to be unique.')
56 return 58 return
57 } 59 }
58 60
59 const confirmMessage = 'If you confirm, you will send a follow request to:<br /> - ' + hosts.join('<br /> - ') 61 const confirmMessage = this.i18n('If you confirm, you will send a follow request to:<br /> - ') + hosts.join('<br /> - ')
60 const res = await this.confirmService.confirm(confirmMessage, 'Follow new server(s)') 62 const res = await this.confirmService.confirm(confirmMessage, this.i18n('Follow new server(s)'))
61 if (res === false) return 63 if (res === false) return
62 64
63 this.followService.follow(hosts).subscribe( 65 this.followService.follow(hosts).subscribe(
64 () => { 66 () => {
65 this.notificationsService.success('Success', 'Follow request(s) sent!') 67 this.notificationsService.success(this.i18n('Success'), this.i18n('Follow request(s) sent!'))
66 68
67 setTimeout(() => this.router.navigate([ '/admin/follows/following-list' ]), 500) 69 setTimeout(() => this.router.navigate([ '/admin/follows/following-list' ]), 500)
68 }, 70 },
69 71
70 err => this.notificationsService.error('Error', err.message) 72 err => this.notificationsService.error(this.i18n('Error'), err.message)
71 ) 73 )
72 } 74 }
73 75
@@ -76,10 +78,8 @@ export class FollowingAddComponent {
76 } 78 }
77 79
78 private getNotEmptyHosts () { 80 private getNotEmptyHosts () {
79 const hosts = this.hostsString 81 return this.hostsString
80 .split('\n') 82 .split('\n')
81 .filter(host => host && host.length !== 0) // Eject empty hosts 83 .filter(host => host && host.length !== 0) // Eject empty hosts
82
83 return hosts
84 } 84 }
85} 85}
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.html b/client/src/app/+admin/follows/following-list/following-list.component.html
index 24981d3e9..e4a45e88c 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.html
+++ b/client/src/app/+admin/follows/following-list/following-list.component.html
@@ -4,10 +4,10 @@
4> 4>
5 <ng-template pTemplate="header"> 5 <ng-template pTemplate="header">
6 <tr> 6 <tr>
7 <th style="width: 60px">ID</th> 7 <th i18n style="width: 60px">ID</th>
8 <th>Host</th> 8 <th i18n>Host</th>
9 <th>State</th> 9 <th i18n>State</th>
10 <th pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 10 <th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
11 <th></th> 11 <th></th>
12 </tr> 12 </tr>
13 </ng-template> 13 </ng-template>
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.ts b/client/src/app/+admin/follows/following-list/following-list.component.ts
index 873a5d965..2fb818c90 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.ts
+++ b/client/src/app/+admin/follows/following-list/following-list.component.ts
@@ -5,6 +5,7 @@ import { AccountFollow } from '../../../../../../shared/models/actors/follow.mod
5import { ConfirmService } from '../../../core/confirm/confirm.service' 5import { ConfirmService } from '../../../core/confirm/confirm.service'
6import { RestPagination, RestTable } from '../../../shared' 6import { RestPagination, RestTable } from '../../../shared'
7import { FollowService } from '../shared' 7import { FollowService } from '../shared'
8import { I18n } from '@ngx-translate/i18n-polyfill'
8 9
9@Component({ 10@Component({
10 selector: 'my-followers-list', 11 selector: 'my-followers-list',
@@ -20,7 +21,8 @@ export class FollowingListComponent extends RestTable implements OnInit {
20 constructor ( 21 constructor (
21 private notificationsService: NotificationsService, 22 private notificationsService: NotificationsService,
22 private confirmService: ConfirmService, 23 private confirmService: ConfirmService,
23 private followService: FollowService 24 private followService: FollowService,
25 private i18n: I18n
24 ) { 26 ) {
25 super() 27 super()
26 } 28 }
@@ -30,16 +32,22 @@ export class FollowingListComponent extends RestTable implements OnInit {
30 } 32 }
31 33
32 async removeFollowing (follow: AccountFollow) { 34 async removeFollowing (follow: AccountFollow) {
33 const res = await this.confirmService.confirm(`Do you really want to unfollow ${follow.following.host}?`, 'Unfollow') 35 const res = await this.confirmService.confirm(
36 this.i18n('Do you really want to unfollow {{ host }}?', { host: follow.following.host }),
37 this.i18n('Unfollow')
38 )
34 if (res === false) return 39 if (res === false) return
35 40
36 this.followService.unfollow(follow).subscribe( 41 this.followService.unfollow(follow).subscribe(
37 () => { 42 () => {
38 this.notificationsService.success('Success', `You are not following ${follow.following.host} anymore.`) 43 this.notificationsService.success(
44 this.i18n('Success'),
45 this.i18n('You are not following {{ host }} anymore.', { host: follow.following.host })
46 )
39 this.loadData() 47 this.loadData()
40 }, 48 },
41 49
42 err => this.notificationsService.error('Error', err.message) 50 err => this.notificationsService.error(this.i18n('Error'), err.message)
43 ) 51 )
44 } 52 }
45 53
@@ -51,7 +59,7 @@ export class FollowingListComponent extends RestTable implements OnInit {
51 this.totalRecords = resultList.total 59 this.totalRecords = resultList.total
52 }, 60 },
53 61
54 err => this.notificationsService.error('Error', err.message) 62 err => this.notificationsService.error(this.i18n('Error'), err.message)
55 ) 63 )
56 } 64 }
57} 65}
diff --git a/client/src/app/+admin/follows/follows.component.html b/client/src/app/+admin/follows/follows.component.html
index 71e82059c..a8258bf70 100644
--- a/client/src/app/+admin/follows/follows.component.html
+++ b/client/src/app/+admin/follows/follows.component.html
@@ -1,5 +1,5 @@
1<div class="admin-sub-header"> 1<div class="admin-sub-header">
2 <div class="form-sub-title">Manage follows</div> 2 <div i18n class="form-sub-title">Manage follows</div>
3 3
4 <tabset #followsMenuTabs> 4 <tabset #followsMenuTabs>
5 <tab *ngFor="let link of links"> 5 <tab *ngFor="let link of links">
diff --git a/client/src/app/+admin/jobs/index.ts b/client/src/app/+admin/jobs/index.ts
index 7b5271956..c0e0cc95d 100644
--- a/client/src/app/+admin/jobs/index.ts
+++ b/client/src/app/+admin/jobs/index.ts
@@ -1 +1,4 @@
1export * from './' 1export * from './shared'
2export * from './jobs-list'
3export * from './job.routes'
4export * from './job.component'
diff --git a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.html b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.html
index 0cc4dc3e0..20c35cb5b 100644
--- a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.html
+++ b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.html
@@ -1,5 +1,5 @@
1<div class="admin-sub-header"> 1<div class="admin-sub-header">
2 <div class="form-sub-title">Jobs list</div> 2 <div i18n class="form-sub-title">Jobs list</div>
3 3
4 <div class="peertube-select-container"> 4 <div class="peertube-select-container">
5 <select [(ngModel)]="jobState" (ngModelChange)="onJobStateChanged()"> 5 <select [(ngModel)]="jobState" (ngModelChange)="onJobStateChanged()">
@@ -15,11 +15,11 @@
15 <ng-template pTemplate="header"> 15 <ng-template pTemplate="header">
16 <tr> 16 <tr>
17 <th style="width: 27px"></th> 17 <th style="width: 27px"></th>
18 <th style="width: 60px">ID</th> 18 <th i18n style="width: 60px">ID</th>
19 <th style="width: 210px">Type</th> 19 <th i18n style="width: 210px">Type</th>
20 <th style="width: 130px">State</th> 20 <th i18n style="width: 130px">State</th>
21 <th style="width: 250px" pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 21 <th i18n style="width: 250px" pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
22 <th style="width: 250px">Updated</th> 22 <th i18n style="width: 250px">Updated</th>
23 </tr> 23 </tr>
24 </ng-template> 24 </ng-template>
25 25
diff --git a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts
index ad2f05c6b..29dd9f31c 100644
--- a/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts
+++ b/client/src/app/+admin/jobs/jobs-list/jobs-list.component.ts
@@ -7,6 +7,7 @@ import { JobState } from '../../../../../../shared/models'
7import { RestPagination, RestTable } from '../../../shared' 7import { RestPagination, RestTable } from '../../../shared'
8import { RestExtractor } from '../../../shared/rest/rest-extractor.service' 8import { RestExtractor } from '../../../shared/rest/rest-extractor.service'
9import { JobService } from '../shared' 9import { JobService } from '../shared'
10import { I18n } from '@ngx-translate/i18n-polyfill'
10 11
11@Component({ 12@Component({
12 selector: 'my-jobs-list', 13 selector: 'my-jobs-list',
@@ -27,7 +28,8 @@ export class JobsListComponent extends RestTable implements OnInit {
27 constructor ( 28 constructor (
28 private notificationsService: NotificationsService, 29 private notificationsService: NotificationsService,
29 private restExtractor: RestExtractor, 30 private restExtractor: RestExtractor,
30 private jobsService: JobService 31 private jobsService: JobService,
32 private i18n: I18n
31 ) { 33 ) {
32 super() 34 super()
33 } 35 }
@@ -51,7 +53,7 @@ export class JobsListComponent extends RestTable implements OnInit {
51 this.totalRecords = resultList.total 53 this.totalRecords = resultList.total
52 }, 54 },
53 55
54 err => this.notificationsService.error('Error', err.message) 56 err => this.notificationsService.error(this.i18n('Error'), err.message)
55 ) 57 )
56 } 58 }
57 59
diff --git a/client/src/app/+admin/users/shared/user.service.ts b/client/src/app/+admin/users/shared/user.service.ts
index 578cd98c3..d8b00b862 100644
--- a/client/src/app/+admin/users/shared/user.service.ts
+++ b/client/src/app/+admin/users/shared/user.service.ts
@@ -7,6 +7,7 @@ import { Observable } from 'rxjs'
7import { ResultList, UserCreate, UserUpdate } from '../../../../../../shared' 7import { ResultList, UserCreate, UserUpdate } from '../../../../../../shared'
8import { environment } from '../../../../environments/environment' 8import { environment } from '../../../../environments/environment'
9import { RestExtractor, RestPagination, RestService, User } from '../../../shared' 9import { RestExtractor, RestPagination, RestService, User } from '../../../shared'
10import { I18n } from '@ngx-translate/i18n-polyfill'
10 11
11@Injectable() 12@Injectable()
12export class UserService { 13export class UserService {
@@ -16,9 +17,9 @@ export class UserService {
16 constructor ( 17 constructor (
17 private authHttp: HttpClient, 18 private authHttp: HttpClient,
18 private restService: RestService, 19 private restService: RestService,
19 private restExtractor: RestExtractor 20 private restExtractor: RestExtractor,
20 ) { 21 private i18n: I18n
21 } 22 ) { }
22 23
23 addUser (userCreate: UserCreate) { 24 addUser (userCreate: UserCreate) {
24 return this.authHttp.post(UserService.BASE_USERS_URL, userCreate) 25 return this.authHttp.post(UserService.BASE_USERS_URL, userCreate)
diff --git a/client/src/app/+admin/users/user-edit/user-create.component.ts b/client/src/app/+admin/users/user-edit/user-create.component.ts
index 2a9882cde..b91ffa115 100644
--- a/client/src/app/+admin/users/user-edit/user-create.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-create.component.ts
@@ -1,20 +1,13 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { FormBuilder, FormGroup } from '@angular/forms' 2import { FormBuilder, FormGroup } from '@angular/forms'
3import { Router } from '@angular/router' 3import { Router } from '@angular/router'
4
5import { NotificationsService } from 'angular2-notifications' 4import { NotificationsService } from 'angular2-notifications'
6
7import { UserService } from '../shared' 5import { UserService } from '../shared'
8import { 6import { USER_EMAIL, USER_PASSWORD, USER_ROLE, USER_USERNAME, USER_VIDEO_QUOTA } from '../../../shared'
9 USER_USERNAME,
10 USER_EMAIL,
11 USER_PASSWORD,
12 USER_VIDEO_QUOTA,
13 USER_ROLE
14} from '../../../shared'
15import { ServerService } from '../../../core' 7import { ServerService } from '../../../core'
16import { UserCreate, UserRole } from '../../../../../../shared' 8import { UserCreate, UserRole } from '../../../../../../shared'
17import { UserEdit } from './user-edit' 9import { UserEdit } from './user-edit'
10import { I18n } from '@ngx-translate/i18n-polyfill'
18 11
19@Component({ 12@Component({
20 selector: 'my-user-create', 13 selector: 'my-user-create',
@@ -45,7 +38,8 @@ export class UserCreateComponent extends UserEdit implements OnInit {
45 private formBuilder: FormBuilder, 38 private formBuilder: FormBuilder,
46 private router: Router, 39 private router: Router,
47 private notificationsService: NotificationsService, 40 private notificationsService: NotificationsService,
48 private userService: UserService 41 private userService: UserService,
42 private i18n: I18n
49 ) { 43 ) {
50 super() 44 super()
51 } 45 }
@@ -76,7 +70,10 @@ export class UserCreateComponent extends UserEdit implements OnInit {
76 70
77 this.userService.addUser(userCreate).subscribe( 71 this.userService.addUser(userCreate).subscribe(
78 () => { 72 () => {
79 this.notificationsService.success('Success', `User ${userCreate.username} created.`) 73 this.notificationsService.success(
74 this.i18n('Success'),
75 this.i18n('User {{ username }} created.', { username: userCreate.username })
76 )
80 this.router.navigate([ '/admin/users/list' ]) 77 this.router.navigate([ '/admin/users/list' ])
81 }, 78 },
82 79
@@ -89,6 +86,6 @@ export class UserCreateComponent extends UserEdit implements OnInit {
89 } 86 }
90 87
91 getFormButtonTitle () { 88 getFormButtonTitle () {
92 return 'Create user' 89 return this.i18n('Create user')
93 } 90 }
94} 91}
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html
index a8c0ddadb..4626a40c9 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.component.html
+++ b/client/src/app/+admin/users/user-edit/user-edit.component.html
@@ -1,13 +1,13 @@
1<div class="form-sub-title" *ngIf="isCreation() === true">Create user</div> 1<div i18n class="form-sub-title" *ngIf="isCreation() === true">Create user</div>
2<div class="form-sub-title" *ngIf="isCreation() === false">Edit user {{ username }}</div> 2<div i18n class="form-sub-title" *ngIf="isCreation() === false">Edit user {{ username }}</div>
3 3
4<div *ngIf="error" class="alert alert-danger">{{ error }}</div> 4<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
5 5
6<form role="form" (ngSubmit)="formValidated()" [formGroup]="form"> 6<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">
7 <div class="form-group" *ngIf="isCreation()"> 7 <div class="form-group" *ngIf="isCreation()">
8 <label for="username">Username</label> 8 <label i18n for="username">Username</label>
9 <input 9 <input
10 type="text" id="username" placeholder="john" 10 type="text" id="username" i18n-placeholder placeholder="john"
11 formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }" 11 formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }"
12 > 12 >
13 <div *ngIf="formErrors.username" class="form-error"> 13 <div *ngIf="formErrors.username" class="form-error">
@@ -16,9 +16,9 @@
16 </div> 16 </div>
17 17
18 <div class="form-group"> 18 <div class="form-group">
19 <label for="email">Email</label> 19 <label i18n for="email">Email</label>
20 <input 20 <input
21 type="text" id="email" placeholder="mail@example.com" 21 type="text" id="email" i18n-placeholder placeholder="mail@example.com"
22 formControlName="email" [ngClass]="{ 'input-error': formErrors['email'] }" 22 formControlName="email" [ngClass]="{ 'input-error': formErrors['email'] }"
23 > 23 >
24 <div *ngIf="formErrors.email" class="form-error"> 24 <div *ngIf="formErrors.email" class="form-error">
@@ -27,7 +27,7 @@
27 </div> 27 </div>
28 28
29 <div class="form-group" *ngIf="isCreation()"> 29 <div class="form-group" *ngIf="isCreation()">
30 <label for="password">Password</label> 30 <label i18n for="password">Password</label>
31 <input 31 <input
32 type="password" id="password" 32 type="password" id="password"
33 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 33 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
@@ -38,7 +38,7 @@
38 </div> 38 </div>
39 39
40 <div class="form-group"> 40 <div class="form-group">
41 <label for="role">Role</label> 41 <label i18n for="role">Role</label>
42 <div class="peertube-select-container"> 42 <div class="peertube-select-container">
43 <select id="role" formControlName="role"> 43 <select id="role" formControlName="role">
44 <option *ngFor="let role of roles" [value]="role.value"> 44 <option *ngFor="let role of roles" [value]="role.value">
@@ -53,7 +53,7 @@
53 </div> 53 </div>
54 54
55 <div class="form-group"> 55 <div class="form-group">
56 <label for="videoQuota">Video quota</label> 56 <label i18n for="videoQuota">Video quota</label>
57 <div class="peertube-select-container"> 57 <div class="peertube-select-container">
58 <select id="videoQuota" formControlName="videoQuota"> 58 <select id="videoQuota" formControlName="videoQuota">
59 <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value"> 59 <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
@@ -62,7 +62,7 @@
62 </select> 62 </select>
63 </div> 63 </div>
64 64
65 <div class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()"> 65 <div i18n class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()">
66 Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br /> 66 Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br />
67 At most, this user could use ~ {{ computeQuotaWithTranscoding() | bytes: 0 }}. 67 At most, this user could use ~ {{ computeQuotaWithTranscoding() | bytes: 0 }}.
68 </div> 68 </div>
diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts
index 3cde07c65..dca555706 100644
--- a/client/src/app/+admin/users/user-edit/user-update.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-update.component.ts
@@ -8,6 +8,7 @@ import { User, USER_EMAIL, USER_ROLE, USER_VIDEO_QUOTA } from '../../../shared'
8import { ServerService } from '../../../core' 8import { ServerService } from '../../../core'
9import { UserEdit } from './user-edit' 9import { UserEdit } from './user-edit'
10import { UserUpdate } from '../../../../../../shared' 10import { UserUpdate } from '../../../../../../shared'
11import { I18n } from '@ngx-translate/i18n-polyfill'
11 12
12@Component({ 13@Component({
13 selector: 'my-user-update', 14 selector: 'my-user-update',
@@ -39,7 +40,8 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
39 private router: Router, 40 private router: Router,
40 private notificationsService: NotificationsService, 41 private notificationsService: NotificationsService,
41 private formBuilder: FormBuilder, 42 private formBuilder: FormBuilder,
42 private userService: UserService 43 private userService: UserService,
44 private i18n: I18n
43 ) { 45 ) {
44 super() 46 super()
45 } 47 }
@@ -81,7 +83,10 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
81 83
82 this.userService.updateUser(this.userId, userUpdate).subscribe( 84 this.userService.updateUser(this.userId, userUpdate).subscribe(
83 () => { 85 () => {
84 this.notificationsService.success('Success', `User ${this.username} updated.`) 86 this.notificationsService.success(
87 this.i18n('Success'),
88 this.i18n('User {{ username }} updated.', { username: this.username })
89 )
85 this.router.navigate([ '/admin/users/list' ]) 90 this.router.navigate([ '/admin/users/list' ])
86 }, 91 },
87 92
@@ -94,7 +99,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
94 } 99 }
95 100
96 getFormButtonTitle () { 101 getFormButtonTitle () {
97 return 'Update user' 102 return this.i18n('Update user')
98 } 103 }
99 104
100 private onUserFetched (userJson: User) { 105 private onUserFetched (userJson: User) {
diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html
index 09a4ac1e7..166fafef0 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.html
+++ b/client/src/app/+admin/users/user-list/user-list.component.html
@@ -1,9 +1,9 @@
1<div class="admin-sub-header"> 1<div class="admin-sub-header">
2 <div class="form-sub-title">Users list</div> 2 <div i18n class="form-sub-title">Users list</div>
3 3
4 <a class="add-button" routerLink="/admin/users/create"> 4 <a class="add-button" routerLink="/admin/users/create">
5 <span class="icon icon-add"></span> 5 <span class="icon icon-add"></span>
6 Create user 6 <ng-container i18n>Create user</ng-container>
7 </a> 7 </a>
8</div> 8</div>
9 9
@@ -13,11 +13,11 @@
13> 13>
14 <ng-template pTemplate="header"> 14 <ng-template pTemplate="header">
15 <tr> 15 <tr>
16 <th pSortableColumn="username">Username <p-sortIcon field="username"></p-sortIcon></th> 16 <th i18n pSortableColumn="username">Username <p-sortIcon field="username"></p-sortIcon></th>
17 <th>Email</th> 17 <th i18n>Email</th>
18 <th>Video quota</th> 18 <th i18n>Video quota</th>
19 <th>Role</th> 19 <th i18n>Role</th>
20 <th pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 20 <th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
21 <th></th> 21 <th></th>
22 </tr> 22 </tr>
23 </ng-template> 23 </ng-template>
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts
index 2cc4d4349..b644fcf71 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/users/user-list/user-list.component.ts
@@ -1,11 +1,10 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2
3import { NotificationsService } from 'angular2-notifications' 2import { NotificationsService } from 'angular2-notifications'
4import { SortMeta } from 'primeng/components/common/sortmeta' 3import { SortMeta } from 'primeng/components/common/sortmeta'
5
6import { ConfirmService } from '../../../core' 4import { ConfirmService } from '../../../core'
7import { RestPagination, RestTable, User } from '../../../shared' 5import { RestPagination, RestTable, User } from '../../../shared'
8import { UserService } from '../shared' 6import { UserService } from '../shared'
7import { I18n } from '@ngx-translate/i18n-polyfill'
9 8
10@Component({ 9@Component({
11 selector: 'my-user-list', 10 selector: 'my-user-list',
@@ -22,7 +21,8 @@ export class UserListComponent extends RestTable implements OnInit {
22 constructor ( 21 constructor (
23 private notificationsService: NotificationsService, 22 private notificationsService: NotificationsService,
24 private confirmService: ConfirmService, 23 private confirmService: ConfirmService,
25 private userService: UserService 24 private userService: UserService,
25 private i18n: I18n
26 ) { 26 ) {
27 super() 27 super()
28 } 28 }
@@ -33,20 +33,23 @@ export class UserListComponent extends RestTable implements OnInit {
33 33
34 async removeUser (user: User) { 34 async removeUser (user: User) {
35 if (user.username === 'root') { 35 if (user.username === 'root') {
36 this.notificationsService.error('Error', 'You cannot delete root.') 36 this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot delete root.'))
37 return 37 return
38 } 38 }
39 39
40 const res = await this.confirmService.confirm('Do you really want to delete this user?', 'Delete') 40 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this user?'), this.i18n('Delete'))
41 if (res === false) return 41 if (res === false) return
42 42
43 this.userService.removeUser(user).subscribe( 43 this.userService.removeUser(user).subscribe(
44 () => { 44 () => {
45 this.notificationsService.success('Success', `User ${user.username} deleted.`) 45 this.notificationsService.success(
46 this.i18n('Success'),
47 this.i18n('User {{ username }} deleted.', { username: user.username })
48 )
46 this.loadData() 49 this.loadData()
47 }, 50 },
48 51
49 err => this.notificationsService.error('Error', err.message) 52 err => this.notificationsService.error(this.i18n('Error'), err.message)
50 ) 53 )
51 } 54 }
52 55
@@ -62,7 +65,7 @@ export class UserListComponent extends RestTable implements OnInit {
62 this.totalRecords = resultList.total 65 this.totalRecords = resultList.total
63 }, 66 },
64 67
65 err => this.notificationsService.error('Error', err.message) 68 err => this.notificationsService.error(this.i18n('Error'), err.message)
66 ) 69 )
67 } 70 }
68} 71}
diff --git a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
index 5f70db991..8111e5f73 100644
--- a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
+++ b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
@@ -1,5 +1,5 @@
1<div class="admin-sub-header"> 1<div class="admin-sub-header">
2 <div class="form-sub-title">Video abuses list</div> 2 <div i18n class="form-sub-title">Video abuses list</div>
3</div> 3</div>
4 4
5<p-table 5<p-table
@@ -8,10 +8,10 @@
8> 8>
9 <ng-template pTemplate="header"> 9 <ng-template pTemplate="header">
10 <tr> 10 <tr>
11 <th>Reason</th> 11 <th i18n>Reason</th>
12 <th>Reporter</th> 12 <th i18n>Reporter</th>
13 <th pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 13 <th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
14 <th>Video</th> 14 <th i18n>Video</th>
15 </tr> 15 </tr>
16 </ng-template> 16 </ng-template>
17 17
@@ -19,13 +19,13 @@
19 <tr> 19 <tr>
20 <td>{{ videoAbuse.reason }}</td> 20 <td>{{ videoAbuse.reason }}</td>
21 <td> 21 <td>
22 <a [href]="videoAbuse.reporterAccount.url" title="Go to the account" target="_blank" rel="noopener noreferrer"> 22 <a [href]="videoAbuse.reporterAccount.url" i18n-title title="Go to the account" target="_blank" rel="noopener noreferrer">
23 {{ createByString(videoAbuse.reporterAccount) }} 23 {{ createByString(videoAbuse.reporterAccount) }}
24 </a> 24 </a>
25 </td> 25 </td>
26 <td>{{ videoAbuse.createdAt }}</td> 26 <td>{{ videoAbuse.createdAt }}</td>
27 <td> 27 <td>
28 <a [href]="videoAbuse.video.url" title="Go to the video" target="_blank" rel="noopener noreferrer"> 28 <a [href]="videoAbuse.video.url" i18n-title title="Go to the video" target="_blank" rel="noopener noreferrer">
29 {{ videoAbuse.video.name }} 29 {{ videoAbuse.video.name }}
30 </a> 30 </a>
31 </td> 31 </td>
diff --git a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts
index b650194b7..6ddebff7e 100644
--- a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts
+++ b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.ts
@@ -5,6 +5,7 @@ import { SortMeta } from 'primeng/components/common/sortmeta'
5import { VideoAbuse } from '../../../../../../shared' 5import { VideoAbuse } from '../../../../../../shared'
6 6
7import { RestPagination, RestTable, VideoAbuseService } from '../../../shared' 7import { RestPagination, RestTable, VideoAbuseService } from '../../../shared'
8import { I18n } from '@ngx-translate/i18n-polyfill'
8 9
9@Component({ 10@Component({
10 selector: 'my-video-abuse-list', 11 selector: 'my-video-abuse-list',
@@ -20,7 +21,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
20 21
21 constructor ( 22 constructor (
22 private notificationsService: NotificationsService, 23 private notificationsService: NotificationsService,
23 private videoAbuseService: VideoAbuseService 24 private videoAbuseService: VideoAbuseService,
25 private i18n: I18n
24 ) { 26 ) {
25 super() 27 super()
26 } 28 }
@@ -41,7 +43,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
41 this.totalRecords = resultList.total 43 this.totalRecords = resultList.total
42 }, 44 },
43 45
44 err => this.notificationsService.error('Error', err.message) 46 err => this.notificationsService.error(this.i18n('Error'), err.message)
45 ) 47 )
46 } 48 }
47} 49}
diff --git a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html
index 0a0fcb762..04f0e3b5c 100644
--- a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html
+++ b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.html
@@ -1,5 +1,5 @@
1<div class="admin-sub-header"> 1<div class="admin-sub-header">
2 <div class="form-sub-title">Blacklisted videos</div> 2 <div i18n class="form-sub-title">Blacklisted videos</div>
3</div> 3</div>
4 4
5<p-table 5<p-table
@@ -8,12 +8,12 @@
8> 8>
9 <ng-template pTemplate="header"> 9 <ng-template pTemplate="header">
10 <tr> 10 <tr>
11 <th pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th> 11 <th i18n pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th>
12 <th>Description</th> 12 <th i18n>Description</th>
13 <th pSortableColumn="views">Views <p-sortIcon field="views"></p-sortIcon></th> 13 <th i18n pSortableColumn="views">Views <p-sortIcon field="views"></p-sortIcon></th>
14 <th>NSFW</th> 14 <th i18n>NSFW</th>
15 <th>UUID</th> 15 <th i18n>UUID</th>
16 <th pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 16 <th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
17 <th></th> 17 <th></th>
18 </tr> 18 </tr>
19 </ng-template> 19 </ng-template>
@@ -27,7 +27,7 @@
27 <td>{{ videoBlacklist.uuid }}</td> 27 <td>{{ videoBlacklist.uuid }}</td>
28 <td>{{ videoBlacklist.createdAt }}</td> 28 <td>{{ videoBlacklist.createdAt }}</td>
29 <td class="action-cell"> 29 <td class="action-cell">
30 <my-delete-button label="Unblacklist" (click)="removeVideoFromBlacklist(videoBlacklist)"></my-delete-button> 30 <my-delete-button i18n-label label="Unblacklist" (click)="removeVideoFromBlacklist(videoBlacklist)"></my-delete-button>
31 </td> 31 </td>
32 </tr> 32 </tr>
33 </ng-template> 33 </ng-template>
diff --git a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts
index 7210e677c..1864e5f65 100644
--- a/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts
+++ b/client/src/app/+admin/video-blacklist/video-blacklist-list/video-blacklist-list.component.ts
@@ -1,11 +1,10 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { SortMeta } from 'primeng/components/common/sortmeta' 2import { SortMeta } from 'primeng/components/common/sortmeta'
3
4import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
5
6import { ConfirmService } from '../../../core' 4import { ConfirmService } from '../../../core'
7import { VideoBlacklistService, RestTable, RestPagination } from '../../../shared' 5import { RestPagination, RestTable, VideoBlacklistService } from '../../../shared'
8import { BlacklistedVideo } from '../../../../../../shared' 6import { BlacklistedVideo } from '../../../../../../shared'
7import { I18n } from '@ngx-translate/i18n-polyfill'
9 8
10@Component({ 9@Component({
11 selector: 'my-video-blacklist-list', 10 selector: 'my-video-blacklist-list',
@@ -22,7 +21,8 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
22 constructor ( 21 constructor (
23 private notificationsService: NotificationsService, 22 private notificationsService: NotificationsService,
24 private confirmService: ConfirmService, 23 private confirmService: ConfirmService,
25 private videoBlacklistService: VideoBlacklistService 24 private videoBlacklistService: VideoBlacklistService,
25 private i18n: I18n
26 ) { 26 ) {
27 super() 27 super()
28 } 28 }
@@ -32,18 +32,23 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
32 } 32 }
33 33
34 async removeVideoFromBlacklist (entry: BlacklistedVideo) { 34 async removeVideoFromBlacklist (entry: BlacklistedVideo) {
35 const confirmMessage = 'Do you really want to remove this video from the blacklist ? It will be available again in the videos list.' 35 const confirmMessage = this.i18n(
36 'Do you really want to remove this video from the blacklist ? It will be available again in the videos list.'
37 )
36 38
37 const res = await this.confirmService.confirm(confirmMessage, 'Unblacklist') 39 const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblacklist'))
38 if (res === false) return 40 if (res === false) return
39 41
40 this.videoBlacklistService.removeVideoFromBlacklist(entry.videoId).subscribe( 42 this.videoBlacklistService.removeVideoFromBlacklist(entry.videoId).subscribe(
41 () => { 43 () => {
42 this.notificationsService.success('Success', `Video ${entry.name} removed from the blacklist.`) 44 this.notificationsService.success(
45 this.i18n('Success'),
46 this.i18n('Video {{ name }} removed from the blacklist.', { name: entry.name })
47 )
43 this.loadData() 48 this.loadData()
44 }, 49 },
45 50
46 err => this.notificationsService.error('Error', err.message) 51 err => this.notificationsService.error(this.i18n('Error'), err.message)
47 ) 52 )
48 } 53 }
49 54
@@ -55,7 +60,7 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
55 this.totalRecords = resultList.total 60 this.totalRecords = resultList.total
56 }, 61 },
57 62
58 err => this.notificationsService.error('Error', err.message) 63 err => this.notificationsService.error(this.i18n('Error'), err.message)
59 ) 64 )
60 } 65 }
61} 66}