1
0
Fork 0

Accessibility fixes for #2149

This commit is contained in:
Rigel Kent 2020-01-10 19:50:48 +01:00 committed by Chocobozzz
parent aa0f19635a
commit 7738273b80
14 changed files with 32 additions and 19 deletions

View File

@ -30,7 +30,7 @@
<div class="form-group" *ngIf="isCreation()"> <div class="form-group" *ngIf="isCreation()">
<label i18n for="password">Password</label> <label i18n for="password">Password</label>
<input <input
type="password" id="password" type="password" id="password" autocomplete="new-password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
> >
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">

View File

@ -24,7 +24,7 @@
<div class="form-group"> <div class="form-group">
<input <input
type="password" id="password" i18n-placeholder placeholder="Your password" type="password" id="password" i18n-placeholder placeholder="Your password" autocomplete="off"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
> >
<div *ngIf="formErrors['password']" class="form-error"> <div *ngIf="formErrors['password']" class="form-error">

View File

@ -4,7 +4,7 @@
<label i18n for="current-password">Change password</label> <label i18n for="current-password">Change password</label>
<input <input
type="password" id="current-password" i18n-placeholder placeholder="Current password" type="password" id="current-password" i18n-placeholder placeholder="Current password" autocomplete="current-password"
formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }" formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }"
> >
<div *ngIf="formErrors['current-password']" class="form-error"> <div *ngIf="formErrors['current-password']" class="form-error">
@ -12,7 +12,7 @@
</div> </div>
<input <input
type="password" id="new-password" i18n-placeholder placeholder="New password" type="password" id="new-password" i18n-placeholder placeholder="New password" autocomplete="new-password"
formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }" formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }"
> >
<div *ngIf="formErrors['new-password']" class="form-error"> <div *ngIf="formErrors['new-password']" class="form-error">
@ -20,7 +20,7 @@
</div> </div>
<input <input
type="password" id="new-confirmed-password" i18n-placeholder placeholder="Confirm new password" type="password" id="new-confirmed-password" i18n-placeholder placeholder="Confirm new password" autocomplete="new-password"
formControlName="new-confirmed-password" formControlName="new-confirmed-password"
> >
<div *ngIf="formErrors['new-confirmed-password']" class="form-error"> <div *ngIf="formErrors['new-confirmed-password']" class="form-error">

View File

@ -51,7 +51,7 @@
<div class="form-group"> <div class="form-group">
<label for="password" i18n>Password</label> <label for="password" i18n>Password</label>
<input <input
type="password" id="password" i18n-placeholder placeholder="Password" type="password" id="password" i18n-placeholder placeholder="Password" autocomplete="new-password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
> >
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">

View File

@ -72,7 +72,7 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
.getVideoChannelVideos(this.videoChannel, newPagination, this.sort) .getVideoChannelVideos(this.videoChannel, newPagination, this.sort)
.pipe( .pipe(
tap(({ total }) => { tap(({ total }) => {
this.titlePage = this.i18n('Published {{total}} videos', { total }) this.titlePage = this.i18n(`{total, plural, =1 {Published 1 video} other {Published ${total} videos}}`, { total })
}) })
) )
} }

View File

@ -20,7 +20,7 @@
<my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button> <my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
</div> </div>
</div> </div>
<div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div> <div class="actor-followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
<a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Go the owner account page" class="actor-owner"> <a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Go the owner account page" class="actor-owner">
<span i18n>Created by {{ videoChannel.ownerBy }}</span> <span i18n>Created by {{ videoChannel.ownerBy }}</span>

View File

@ -1,5 +1,5 @@
<input <input
type="text" id="search-video" name="search-video" i18n-placeholder placeholder="Search videos, channels…" type="text" id="search-video" name="search-video" [attr.aria-label]="ariaLabelTextForSearch" i18n-placeholder placeholder="Search videos, channels…"
[(ngModel)]="searchValue" (keyup.enter)="doSearch()" [(ngModel)]="searchValue" (keyup.enter)="doSearch()"
> >
<span (click)="doSearch()" class="icon icon-search"></span> <span (click)="doSearch()" class="icon icon-search"></span>

View File

@ -5,6 +5,7 @@ import { getParameterByName } from '../shared/misc/utils'
import { AuthService, ServerService, Notifier } from '@app/core' import { AuthService, ServerService, Notifier } from '@app/core'
import { of } from 'rxjs' import { of } from 'rxjs'
import { ServerConfig } from '@shared/models' import { ServerConfig } from '@shared/models'
import { I18n } from '@ngx-translate/i18n-polyfill'
@Component({ @Component({
selector: 'my-header', selector: 'my-header',
@ -14,6 +15,7 @@ import { ServerConfig } from '@shared/models'
export class HeaderComponent implements OnInit { export class HeaderComponent implements OnInit {
searchValue = '' searchValue = ''
ariaLabelTextForSearch = ''
private serverConfig: ServerConfig private serverConfig: ServerConfig
@ -23,10 +25,13 @@ export class HeaderComponent implements OnInit {
private auth: AuthService, private auth: AuthService,
private serverService: ServerService, private serverService: ServerService,
private authService: AuthService, private authService: AuthService,
private notifier: Notifier private notifier: Notifier,
private i18n: I18n
) {} ) {}
ngOnInit () { ngOnInit () {
this.ariaLabelTextForSearch = this.i18n('Search videos, channels')
this.router.events this.router.events
.pipe( .pipe(
filter(e => e instanceof NavigationEnd), filter(e => e instanceof NavigationEnd),

View File

@ -51,7 +51,7 @@
<label i18n for="password">Password</label> <label i18n for="password">Password</label>
<div> <div>
<input <input
type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" autocomplete="current-password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
> >
<a i18n class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> <a i18n class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a>

View File

@ -7,7 +7,7 @@
<div class="form-group"> <div class="form-group">
<label i18n for="password">Password</label> <label i18n for="password">Password</label>
<input <input
type="password" name="password" id="password" i18n-placeholder placeholder="Password" required type="password" name="password" id="password" i18n-placeholder placeholder="Password" required autocomplete="new-password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
> >
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">
@ -18,7 +18,7 @@
<div class="form-group"> <div class="form-group">
<label i18n for="password-confirm">Confirm password</label> <label i18n for="password-confirm">Confirm password</label>
<input <input
type="password" name="password-confirm" id="password-confirm" i18n-placeholder placeholder="Confirmed password" required type="password" name="password-confirm" id="password-confirm" i18n-placeholder placeholder="Confirmed password" required autocomplete="new-password"
formControlName="password-confirm" [ngClass]="{ 'input-error': formErrors['password-confirm'] }" formControlName="password-confirm" [ngClass]="{ 'input-error': formErrors['password-confirm'] }"
> >
<div *ngIf="formErrors['password-confirm']" class="form-error"> <div *ngIf="formErrors['password-confirm']" class="form-error">

View File

@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core' import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core'
import { HooksService } from '@app/core/plugins/hooks.service' import { HooksService } from '@app/core/plugins/hooks.service'
import { I18n } from '@ngx-translate/i18n-polyfill'
const icons = { const icons = {
'add': require('!!raw-loader?!../../../assets/images/global/add.svg'), 'add': require('!!raw-loader?!../../../assets/images/global/add.svg'),
@ -70,8 +71,7 @@ export class GlobalIconComponent implements OnInit {
) { } ) { }
async ngOnInit () { async ngOnInit () {
const nativeElement = this.el.nativeElement const nativeElement = this.el.nativeElement as HTMLElement
nativeElement.innerHTML = await this.hooks.wrapFun( nativeElement.innerHTML = await this.hooks.wrapFun(
this.getSVGContent.bind(this), this.getSVGContent.bind(this),
{ name: this.iconName }, { name: this.iconName },

View File

@ -1,8 +1,8 @@
<a <a
[routerLink]="getVideoRouterLink()" [queryParams]="queryParams" [attr.title]="video.name" [routerLink]="getVideoRouterLink()" [queryParams]="queryParams" [title]="video.name"
class="video-thumbnail" class="video-thumbnail"
> >
<img alt="" [attr.aria-labelledby]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" /> <img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" />
<div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay"> <div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay">
<ng-container *ngIf="inWatchLaterPlaylist !== true"> <ng-container *ngIf="inWatchLaterPlaylist !== true">

View File

@ -8,6 +8,7 @@
font-family: 'Glyphicons Halflings'; font-family: 'Glyphicons Halflings';
text-decoration: none !important; text-decoration: none !important;
color: var(--mainForegroundColor) !important; color: var(--mainForegroundColor) !important;
font-display: swap;
} }
my-edit-button, my-edit-button,

View File

@ -26,7 +26,9 @@ export class ClientHtml {
} }
static async getDefaultHTMLPage (req: express.Request, res: express.Response, paramLang?: string) { static async getDefaultHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
const html = await ClientHtml.getIndexHTML(req, res, paramLang) const html = paramLang
? await ClientHtml.getIndexHTML(req, res, paramLang)
: await ClientHtml.getIndexHTML(req, res)
let customHtml = ClientHtml.addTitleTag(html) let customHtml = ClientHtml.addTitleTag(html)
customHtml = ClientHtml.addDescriptionTag(customHtml) customHtml = ClientHtml.addDescriptionTag(customHtml)
@ -98,6 +100,7 @@ export class ClientHtml {
let html = buffer.toString() let html = buffer.toString()
if (paramLang) html = ClientHtml.addHtmlLang(html, paramLang)
html = ClientHtml.addCustomCSS(html) html = ClientHtml.addCustomCSS(html)
html = await ClientHtml.addAsyncPluginCSS(html) html = await ClientHtml.addAsyncPluginCSS(html)
@ -106,7 +109,7 @@ export class ClientHtml {
return html return html
} }
private static getIndexPath (req: express.Request, res: express.Response, paramLang?: string) { private static getIndexPath (req: express.Request, res: express.Response, paramLang: string) {
let lang: string let lang: string
// Check param lang validity // Check param lang validity
@ -129,6 +132,10 @@ export class ClientHtml {
return join(__dirname, '../../../client/dist/' + buildFileLocale(lang) + '/index.html') return join(__dirname, '../../../client/dist/' + buildFileLocale(lang) + '/index.html')
} }
private static addHtmlLang (htmlStringPage: string, paramLang: string) {
return htmlStringPage.replace('<html>', `<html lang="${paramLang}">`)
}
private static addTitleTag (htmlStringPage: string, title?: string) { private static addTitleTag (htmlStringPage: string, title?: string) {
let text = title || CONFIG.INSTANCE.NAME let text = title || CONFIG.INSTANCE.NAME
if (title) text += ` - ${CONFIG.INSTANCE.NAME}` if (title) text += ` - ${CONFIG.INSTANCE.NAME}`