on:
push:
- branches:
- - develop
- - master
- - ci
- - next
pull_request:
types: [synchronize, opened]
schedule:
import { InstanceService } from '@app/shared/shared-instance'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { HTMLServerConfig } from '@shared/models'
+import { HTMLServerConfig, HttpStatusCode } from '@shared/models'
type Prefill = {
subject?: string
VideoService
} from '@app/shared/shared-main'
import { AccountReportComponent } from '@app/shared/shared-moderation'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { User, UserRight } from '@shared/models'
+import { HttpStatusCode, User, UserRight } from '@shared/models'
import { AccountSearchComponent } from './account-search/account-search.component'
@Component({
label: $localize`Federation`,
children: [
{
- label: $localize`Instances you follow`,
+ label: $localize`Following`,
routerLink: '/admin/follows/following-list',
iconName: 'following'
},
{
- label: $localize`Instances following you`,
+ label: $localize`Followers`,
routerLink: '/admin/follows/followers-list',
iconName: 'follower'
},
EditVODTranscodingComponent
} from './config'
import { ConfigService } from './config/shared/config.service'
-import { FollowersListComponent, FollowsComponent, VideoRedundanciesListComponent } from './follows'
+import { FollowersListComponent, FollowModalComponent, FollowsComponent, VideoRedundanciesListComponent } from './follows'
import { FollowingListComponent } from './follows/following-list/following-list.component'
import { RedundancyCheckboxComponent } from './follows/shared/redundancy-checkbox.component'
import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component'
FollowsComponent,
FollowersListComponent,
FollowingListComponent,
+ FollowModalComponent,
RedundancyCheckboxComponent,
VideoRedundanciesListComponent,
VideoRedundancyInformationComponent,
<h1>
<my-global-icon iconName="follower" aria-hidden="true"></my-global-icon>
- <ng-container i18n>Instances following you</ng-container>
+ <ng-container i18n>Followers of your instance</ng-container>
</h1>
<p-table
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;" i18n>Actions</th>
- <th i18n>Follower handle</th>
+ <th i18n>Follower</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
--- /dev/null
+<ng-template #modal>
+ <div class="modal-header">
+ <h4 i18n class="modal-title">Follow</h4>
+
+ <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
+ </div>
+
+ <div class="modal-body">
+ <form novalidate [formGroup]="form" (ngSubmit)="submit()">
+ <div class="form-group">
+ <label i18n for="hostsOrHandles">1 host (without "http://"), account handle or channel handle per line</label>
+
+ <textarea
+ [placeholder]="placeholder" formControlName="hostsOrHandles" type="text" id="hostsOrHandles" name="hostsOrHandles"
+ class="form-control" [ngClass]="{ 'input-error': formErrors['hostsOrHandles'] }" ngbAutofocus
+ ></textarea>
+
+ <div *ngIf="formErrors.hostsOrHandles" class="form-error">
+ {{ formErrors.hostsOrHandles }}
+
+ <div *ngIf="form.controls['hostsOrHandles'].errors.validHostsOrHandles">
+ {{ form.controls['hostsOrHandles'].errors.validHostsOrHandles.value }}
+ </div>
+ </div>
+ </div>
+
+ <div i18n *ngIf="httpEnabled() === false" class="alert alert-warning">
+ It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
+ </div>
+
+ <div class="form-group inputs">
+ <input
+ type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button"
+ (click)="hide()" (key.enter)="hide()"
+ >
+
+ <input type="submit" i18n-value value="Follow" class="peertube-button orange-button" [disabled]="!form.valid" />
+ </div>
+ </form>
+ </div>
+
+</ng-template>
--- /dev/null
+textarea {
+ height: 200px;
+}
--- /dev/null
+import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
+import { Notifier } from '@app/core'
+import { splitAndGetNotEmpty, UNIQUE_HOSTS_OR_HANDLE_VALIDATOR } from '@app/shared/form-validators/host-validators'
+import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
+import { InstanceFollowService } from '@app/shared/shared-instance'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
+
+@Component({
+ selector: 'my-follow-modal',
+ templateUrl: './follow-modal.component.html',
+ styleUrls: [ './follow-modal.component.scss' ]
+})
+export class FollowModalComponent extends FormReactive implements OnInit {
+ @ViewChild('modal', { static: true }) modal: NgbModal
+
+ @Output() newFollow = new EventEmitter<void>()
+
+ placeholder = 'example.com\nchocobozzz@example.com\nchocobozzz_channel@example.com'
+
+ private openedModal: NgbModalRef
+
+ constructor (
+ protected formValidatorService: FormValidatorService,
+ private modalService: NgbModal,
+ private followService: InstanceFollowService,
+ private notifier: Notifier
+ ) {
+ super()
+ }
+
+ ngOnInit () {
+ this.buildForm({
+ hostsOrHandles: UNIQUE_HOSTS_OR_HANDLE_VALIDATOR
+ })
+ }
+
+ openModal () {
+ this.openedModal = this.modalService.open(this.modal, { centered: true })
+ }
+
+ hide () {
+ this.openedModal.close()
+ }
+
+ submit () {
+ this.addFollowing()
+
+ this.form.reset()
+ this.hide()
+ }
+
+ httpEnabled () {
+ return window.location.protocol === 'https:'
+ }
+
+ private async addFollowing () {
+ const hostsOrHandles = splitAndGetNotEmpty(this.form.value['hostsOrHandles'])
+
+ this.followService.follow(hostsOrHandles).subscribe(
+ () => {
+ this.notifier.success($localize`Follow request(s) sent!`)
+ this.newFollow.emit()
+ },
+
+ err => this.notifier.error(err.message)
+ )
+ }
+}
<h1>
<my-global-icon iconName="following" aria-hidden="true"></my-global-icon>
- <ng-container i18n>Instances you follow</ng-container>
+ <ng-container i18n>Your instance subscriptions</ng-container>
</h1>
<p-table
<ng-template pTemplate="caption">
<div class="caption">
<div class="left-buttons">
- <a class="follow-button" (click)="addDomainsToFollow()" (key.enter)="addDomainsToFollow()">
+ <a class="follow-button" (click)="openFollowModal()" (key.enter)="openFollowModal()">
<my-global-icon iconName="following" aria-hidden="true"></my-global-icon>
- <ng-container i18n>Follow instances</ng-container>
+ <ng-container i18n>Follow</ng-container>
</a>
</div>
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;" i18n>Action</th>
- <th i18n>Host</th>
+ <th i18n>Following</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 160px;" i18n pSortableColumn="redundancyAllowed">Redundancy allowed <p-sortIcon field="redundancyAllowed"></p-sortIcon></th>
<my-delete-button label="Unfollow" i18n-label (click)="removeFollowing(follow)"></my-delete-button>
</td>
<td>
- <a [href]="'https://' + follow.following.host" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer">
- {{ follow.following.host }}
+ <a [href]="follow.following.url" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer">
+ {{ follow.following.name + '@' + follow.following.host }}
<span class="glyphicon glyphicon-new-window"></span>
</a>
</td>
<td>{{ follow.createdAt | date: 'short' }}</td>
<td>
<my-redundancy-checkbox
+ *ngIf="isInstanceFollowing(follow)"
[host]="follow.following.host" [redundancyAllowed]="follow.following.hostRedundancyAllowed"
></my-redundancy-checkbox>
</td>
</ng-template>
</p-table>
-<my-batch-domains-modal #batchDomainsModal i18n-action action="Follow domains" (domains)="addFollowing($event)">
- <ng-container ngProjectAs="warning">
- <div i18n *ngIf="httpEnabled() === false" class="alert alert-warning">
- It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
- </div>
- </ng-container>
-</my-batch-domains-modal>
+<my-follow-modal #followModal></my-follow-modal>
import { InstanceFollowService } from '@app/shared/shared-instance'
import { BatchDomainsModalComponent } from '@app/shared/shared-moderation'
import { ActorFollow } from '@shared/models'
+import { FollowModalComponent } from './follow-modal.component'
@Component({
templateUrl: './following-list.component.html',
styleUrls: [ '../follows.component.scss', './following-list.component.scss' ]
})
export class FollowingListComponent extends RestTable implements OnInit {
- @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent
+ @ViewChild('followModal') followModal: FollowModalComponent
following: ActorFollow[] = []
totalRecords = 0
return 'FollowingListComponent'
}
- addDomainsToFollow () {
- this.batchDomainsModal.openModal()
+ openFollowModal () {
+ this.followModal.openModal()
}
- httpEnabled () {
- return window.location.protocol === 'https:'
- }
-
- async addFollowing (hosts: string[]) {
- this.followService.follow(hosts).subscribe(
- () => {
- this.notifier.success($localize`Follow request(s) sent!`)
- this.reloadData()
- },
-
- err => this.notifier.error(err.message)
- )
+ isInstanceFollowing (follow: ActorFollow) {
+ return follow.following.name === 'peertube'
}
async removeFollowing (follow: ActorFollow) {
+export * from './follow-modal.component'
export * from './following-list.component'
component: FollowingListComponent,
data: {
meta: {
- title: $localize`Following list`
+ title: $localize`Following`
}
}
},
component: FollowersListComponent,
data: {
meta: {
- title: $localize`Followers list`
+ title: $localize`Followers`
}
}
},
import { SortMeta } from 'primeng/api'
import { switchMap } from 'rxjs/operators'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, OnInit } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
import { AdvancedInputFilter } from '@app/shared/shared-forms'
import { DropdownAction, Video, VideoService } from '@app/shared/shared-main'
import { VideoBlockService } from '@app/shared/shared-moderation'
+import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils'
import { VideoBlacklist, VideoBlacklistType } from '@shared/models'
@Component({
getVideoEmbed (entry: VideoBlacklist) {
return buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: `${environment.originServerUrl}/videos/embed/${entry.video.uuid}`,
+ decorateVideoLink({
+ url: buildVideoEmbedLink(entry.video, environment.originServerUrl),
+
title: false,
warningTitle: false
}),
import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core'
import { PluginService } from '@app/core/plugins/plugin.service'
-import { compareSemVer } from '@shared/core-utils/miscs/miscs'
+import { compareSemVer } from '@shared/core-utils'
import { PeerTubePlugin, PluginType } from '@shared/models'
@Component({
]
this.columns = [
- { id: 'username', label: 'Username' },
- { id: 'email', label: 'Email' },
- { id: 'quota', label: 'Video quota' },
- { id: 'role', label: 'Role' },
- { id: 'createdAt', label: 'Created' }
+ { id: 'username', label: $localize`Username` },
+ { id: 'email', label: $localize`Email` },
+ { id: 'quota', label: $localize`Video quota` },
+ { id: 'role', label: $localize`Role` },
+ { id: 'createdAt', label: $localize`Created` }
]
this.selectedColumns = this.columns.map(c => c.id)
- this.columns.push({ id: 'quotaDaily', label: 'Daily quota' })
- this.columns.push({ id: 'pluginAuth', label: 'Auth plugin' })
- this.columns.push({ id: 'lastLoginDate', label: 'Last login' })
+ this.columns.push({ id: 'quotaDaily', label: $localize`Daily quota` })
+ this.columns.push({ id: 'pluginAuth', label: $localize`Auth plugin` })
+ this.columns.push({ id: 'lastLoginDate', label: $localize`Last login` })
}
getIdentifier () {
<div *ngIf="formErrors.username" class="form-error">
{{ formErrors.username }}
</div>
+
+ <div *ngIf="hasUsernameUppercase()" i18n class="form-warning">
+ ⚠️ Most email addresses do not include capital letters.
+ </div>
</div>
<div class="form-group">
this.accordion = instanceAboutAccordion.accordion
}
+ hasUsernameUppercase () {
+ return this.form.value['username'].match(/[A-Z]/)
+ }
+
private loadExternalAuthToken (username: string, token: string) {
this.isAuthenticatedWithExternalAuth = true
+import { of } from 'rxjs'
+import { switchMap } from 'rxjs/operators'
import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'
import { AuthService, Notifier } from '@app/core'
} from '@app/shared/form-validators/video-channel-validators'
import { FormValidatorService } from '@app/shared/shared-forms'
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
-import { VideoChannelCreate } from '@shared/models'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode, VideoChannelCreate } from '@shared/models'
import { MyVideoChannelEdit } from './my-video-channel-edit'
-import { switchMap } from 'rxjs/operators'
-import { of } from 'rxjs'
@Component({
templateUrl: './my-video-channel-edit.component.html',
It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
channel with the same name (${videoChannel.name})!`,
- $localize`Please type the display name of the video channel (${videoChannel.displayName}) to confirm`,
+ $localize`Please type the name of the video channel (${videoChannel.name}) to confirm`,
- videoChannel.displayName,
+ videoChannel.name,
$localize`Delete`
)
<div class="peertube-select-container peertube-select-button">
<select [(ngModel)]="sort" (ngModelChange)="onChangeSortColumn()" class="form-control">
- <option value="undefined" disabled>Sort by</option>
+ <option value="undefined" disabled i18n>Sort by</option>
<option value="-publishedAt" i18n>Last published first</option>
<option value="-createdAt" i18n>Last created first</option>
<option value="-views" i18n>Most viewed first</option>
import { Component, OnInit } from '@angular/core'
import { Title } from '@angular/platform-browser'
import { Router } from '@angular/router'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
+
@Component({
selector: 'my-page-not-found',
templateUrl: './page-not-found.component.html',
</div>
<div class="peertube-radio-container" *ngFor="let date of publishedDateRanges">
- <input type="radio" (change)="onInputUpdated()" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange">
+ <input type="radio" (change)="onDurationOrPublishedUpdated()" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange">
<label [for]="date.id" class="radio">{{ date.label }}</label>
</div>
</div>
<div class="row">
<div class="pl-0 col-sm-6">
<input
- (change)="onInputUpdated()"
+ (change)="onDurationOrPublishedUpdated()"
(keydown.enter)="$event.preventDefault()"
type="text" id="original-publication-after" name="original-publication-after"
i18n-placeholder placeholder="After..."
</div>
<div class="pr-0 col-sm-6">
<input
- (change)="onInputUpdated()"
+ (change)="onDurationOrPublishedUpdated()"
(keydown.enter)="$event.preventDefault()"
type="text" id="original-publication-before" name="original-publication-before"
i18n-placeholder placeholder="Before..."
</div>
<div class="peertube-radio-container" *ngFor="let duration of durationRanges">
- <input type="radio" (change)="onInputUpdated()" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange">
+ <input type="radio" (change)="onDurationOrPublishedUpdated()" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange">
<label [for]="duration.id" class="radio">{{ duration.label }}</label>
</div>
</div>
<my-select-tags name="tagsOneOf" labelForId="tagsOneOf" id="tagsOneOf" [(ngModel)]="advancedSearch.tagsOneOf"></my-select-tags>
</div>
+ <div class="form-group">
+ <label i18n for="host">PeerTube instance host</label>
+
+ <input (change)="onDurationOrPublishedUpdated()" (keydown.enter)="$event.preventDefault()" type="text" id="host" name="host"
+ placeholder="example.com" [(ngModel)]="advancedSearch.host" class="form-control"
+ >
+ </div>
+
<div class="form-group" *ngIf="isSearchTargetEnabled()">
<div class="radio-label label-container">
<label i18n>Search target</label>
this.loadOriginallyPublishedAtYears()
}
- onInputUpdated () {
+ onDurationOrPublishedUpdated () {
this.updateModelFromDurationRange()
this.updateModelFromPublishedRange()
this.updateModelFromOriginallyPublishedAtYears()
}
formUpdated () {
- this.onInputUpdated()
+ this.onDurationOrPublishedUpdated()
this.filtered.emit(this.advancedSearch)
}
this.durationRange = undefined
this.publishedDateRange = undefined
- this.onInputUpdated()
+ this.onDurationOrPublishedUpdated()
}
resetField (fieldName: string, value?: any) {
resetLocalField (fieldName: string, value?: any) {
this[fieldName] = value
- this.onInputUpdated()
+ this.onDurationOrPublishedUpdated()
}
resetOriginalPublicationYears () {
<div class="results-filter collapse-transition" [ngbCollapse]="isSearchFilterCollapsed">
<my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters>
+
+ <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
</div>
</div>
padding: 40px;
}
+.alert-danger {
+ margin-top: 10px;
+}
+
.results-header {
font-size: 16px;
padding-bottom: 20px;
-import { forkJoin, of, Subscription } from 'rxjs'
+import { forkJoin, Subscription } from 'rxjs'
import { LinkType } from 'src/types/link.type'
import { Component, OnDestroy, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, HooksService, MetaService, Notifier, ServerService, User, UserService } from '@app/core'
import { immutableAssign } from '@app/helpers'
+import { validateHost } from '@app/shared/form-validators/host-validators'
import { Video, VideoChannel } from '@app/shared/shared-main'
import { AdvancedSearch, SearchService } from '@app/shared/shared-search'
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
templateUrl: './search.component.html'
})
export class SearchComponent implements OnInit, OnDestroy {
- results: (Video | VideoChannel)[] = []
+ error: string
+
+ results: (Video | VideoChannel | VideoPlaylist)[] = []
pagination = {
currentPage: 1,
this.advancedSearch.searchTarget = this.getDefaultSearchTarget()
}
- // Don't hide filters if we have some of them AND the user just came on the webpage
- this.isSearchFilterCollapsed = this.isInitialLoad === false || !this.advancedSearch.containsValues()
+ this.error = this.checkFieldsAndGetError()
+
+ // Don't hide filters if we have some of them AND the user just came on the webpage, or we have an error
+ this.isSearchFilterCollapsed = !this.error && (this.isInitialLoad === false || !this.advancedSearch.containsValues())
this.isInitialLoad = false
this.search()
}
search () {
+ this.error = this.checkFieldsAndGetError()
+ if (this.error) return
+
this.isSearching = true
forkJoin([
}
private getVideoChannelObs () {
- if (!this.currentSearch) return of({ data: [], total: 0 })
-
const params = {
search: this.currentSearch,
componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.channelsPerPage }),
- searchTarget: this.advancedSearch.searchTarget
+ advancedSearch: this.advancedSearch
}
return this.hooks.wrapObsFun(
}
private getVideoPlaylistObs () {
- if (!this.currentSearch) return of({ data: [], total: 0 })
-
const params = {
search: this.currentSearch,
componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.playlistsPerPage }),
- searchTarget: this.advancedSearch.searchTarget
+ advancedSearch: this.advancedSearch
}
return this.hooks.wrapObsFun(
return 'local'
}
+
+ private checkFieldsAndGetError () {
+ if (this.advancedSearch.host && !validateHost(this.advancedSearch.host)) {
+ return $localize`PeerTube instance host filter is invalid`
+ }
+
+ return undefined
+ }
}
import { ListOverflowItem, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
import { SupportModalComponent } from '@app/shared/shared-support-modal'
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
@Component({
templateUrl: './video-channels.component.html',
</ng-template>
</my-help>
- <my-markdown-textarea [truncate]="250" formControlName="description" [markdownVideo]="true"></my-markdown-textarea>
+ <my-markdown-textarea [truncate]="250" formControlName="description" [markdownVideo]="videoToUpdate"></my-markdown-textarea>
<div *ngIf="formErrors.description" class="form-error">
{{ formErrors.description }}
import { FormValidatorService } from '@app/shared/shared-forms'
import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
import { LoadingBarService } from '@ngx-loading-bar/core'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { VideoPrivacy } from '@shared/models'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
import { UploaderXFormData } from './uploaderx-form-data'
import { VideoSend } from './video-send'
// Before HTML rendering restore line feed for markdown list compatibility
const commentText = this.comment.text.replace(/<br.?\/?>/g, '\r\n')
const html = await this.markdownService.textMarkdownToHTML(commentText, true, true)
- this.sanitizedCommentHTML = this.markdownService.processVideoTimestamps(html)
+ this.sanitizedCommentHTML = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
this.newParentComments = this.parentComments.concat([ this.comment ])
if (this.comment.account) {
-<div class="video-attribute">
- <span i18n class="video-attribute-label">Privacy</span>
- <span class="video-attribute-value">{{ video.privacy.label }}</span>
+<div class="attribute">
+ <span i18n class="attribute-label">Privacy</span>
+ <span class="attribute-value">{{ video.privacy.label }}</span>
</div>
-<div *ngIf="video.isLocal === false" class="video-attribute">
- <span i18n class="video-attribute-label">Origin</span>
- <a class="video-attribute-value" target="_blank" rel="noopener noreferrer" [href]="getVideoUrl()">{{ video.originInstanceHost }}</a>
+<div *ngIf="video.isLocal === false" class="attribute">
+ <span i18n class="attribute-label">Origin</span>
+ <a
+ class="attribute-value" target="_blank" rel="noopener noreferrer"
+ routerLink="/search" [queryParams]="{ host: getVideoHost() }"
+ >{{ video.originInstanceHost }}</a>
+
+ <a
+ i18n-title title="Open the video on the origin instance" class="glyphicon glyphicon-new-window"
+ target="_blank" rel="noopener noreferrer" [href]="getVideoUrl()"
+ ></a>
</div>
-<div *ngIf="!!video.originallyPublishedAt" class="video-attribute">
- <span i18n class="video-attribute-label">Originally published</span>
- <span class="video-attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span>
+<div *ngIf="!!video.originallyPublishedAt" class="attribute">
+ <span i18n class="attribute-label">Originally published</span>
+ <span class="attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span>
</div>
-<div class="video-attribute">
- <span i18n class="video-attribute-label">Category</span>
- <span *ngIf="!video.category.id" class="video-attribute-value">{{ video.category.label }}</span>
+<div class="attribute">
+ <span i18n class="attribute-label">Category</span>
+ <span *ngIf="!video.category.id" class="attribute-value">{{ video.category.label }}</span>
<a
- *ngIf="video.category.id" class="video-attribute-value"
+ *ngIf="video.category.id" class="attribute-value"
[routerLink]="[ '/search' ]" [queryParams]="{ categoryOneOf: [ video.category.id ] }"
>{{ video.category.label }}</a>
</div>
-<div class="video-attribute">
- <span i18n class="video-attribute-label">Licence</span>
- <span *ngIf="!video.licence.id" class="video-attribute-value">{{ video.licence.label }}</span>
+<div class="attribute">
+ <span i18n class="attribute-label">Licence</span>
+ <span *ngIf="!video.licence.id" class="attribute-value">{{ video.licence.label }}</span>
<a
- *ngIf="video.licence.id" class="video-attribute-value"
+ *ngIf="video.licence.id" class="attribute-value"
[routerLink]="[ '/search' ]" [queryParams]="{ licenceOneOf: [ video.licence.id ] }"
>{{ video.licence.label }}</a>
</div>
-<div class="video-attribute">
- <span i18n class="video-attribute-label">Language</span>
- <span *ngIf="!video.language.id" class="video-attribute-value">{{ video.language.label }}</span>
+<div class="attribute">
+ <span i18n class="attribute-label">Language</span>
+ <span *ngIf="!video.language.id" class="attribute-value">{{ video.language.label }}</span>
<a
- *ngIf="video.language.id" class="video-attribute-value"
+ *ngIf="video.language.id" class="attribute-value"
[routerLink]="[ '/search' ]" [queryParams]="{ languageOneOf: [ video.language.id ] }"
>{{ video.language.label }}</a>
</div>
-<div class="video-attribute video-attribute-tags">
- <span i18n class="video-attribute-label">Tags</span>
+<div class="attribute attribute-tags">
+ <span i18n class="attribute-label">Tags</span>
<a
*ngFor="let tag of getVideoTags()"
- class="video-attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }"
+ class="attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }"
>{{ tag }}</a>
</div>
-<div class="video-attribute" *ngIf="!video.isLive">
- <span i18n class="video-attribute-label">Duration</span>
- <span class="video-attribute-value">{{ video.duration | myDurationFormatter }}</span>
+<div class="attribute" *ngIf="!video.isLive">
+ <span i18n class="attribute-label">Duration</span>
+ <span class="attribute-value">{{ video.duration | myDurationFormatter }}</span>
</div>
@use '_variables' as *;
@use '_mixins' as *;
-.video-attribute {
+.attribute {
font-size: 13px;
display: block;
margin-bottom: 12px;
}
-.video-attribute-label {
+.attribute-label {
@include padding-right(5px);
min-width: 142px;
font-weight: $font-bold;
}
-a.video-attribute-value {
+a.attribute-value {
@include disable-default-a-behaviour;
color: pvar(--mainForegroundColor);
}
}
-.video-attribute-tags {
- .video-attribute-value:not(:nth-child(2)) {
+.attribute-tags {
+ .attribute-value:not(:nth-child(2)) {
&::before {
content: ', ';
}
}
}
+.glyphicon-new-window {
+ color: pvar(--inputPlaceholderColor);
+ margin-left: 5px;
+ font-size: 12px;
+}
+
@media screen and (max-width: 1600px) {
- .video-attributes .video-attribute {
+ .attributes .attribute {
margin-bottom: 5px;
}
}
return this.video.url
}
+ getVideoHost () {
+ return this.video.channel.host
+ }
+
getVideoTags () {
if (!this.video || Array.isArray(this.video.tags) === false) return []
private async setVideoDescriptionHTML () {
const html = await this.markdownService.textMarkdownToHTML(this.video.description)
- this.videoHTMLDescription = this.markdownService.processVideoTimestamps(html)
+
+ this.videoHTMLDescription = this.markdownService.processVideoTimestamps(this.video.shortUUID, html)
}
}
import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main'
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { HTMLServerConfig, PeerTubeProblemDocument, ServerErrorCode, VideoCaption, VideoPrivacy, VideoState } from '@shared/models'
+import { timeToInt } from '@shared/core-utils'
+import {
+ HTMLServerConfig,
+ HttpStatusCode,
+ PeerTubeProblemDocument,
+ ServerErrorCode,
+ VideoCaption,
+ VideoPrivacy,
+ VideoState
+} from '@shared/models'
import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage'
import {
CustomizationOptions,
PlayerMode,
videojs
} from '../../../assets/player/peertube-player-manager'
-import { timeToInt } from '../../../assets/player/utils'
import { environment } from '../../../environments/environment'
import { VideoWatchPlaylistComponent } from './shared'
videoCaptions: playerCaptions,
+ videoShortUUID: video.shortUUID,
videoUUID: video.uuid
},
import { Router } from '@angular/router'
import { Notifier } from '@app/core/notification/notifier.service'
import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index'
-import { MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models'
+import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models'
import { environment } from '../../../environments/environment'
import { RestExtractor } from '../rest/rest-extractor.service'
import { AuthStatus } from './auth-status.model'
import { AuthUser } from './auth-user.model'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
interface UserLoginWithUsername extends UserLogin {
access_token: string
return {
key: 'in-my-library',
- title: 'In my library',
+ title: $localize`In my library`,
links
}
}
import * as MarkdownIt from 'markdown-it'
-import { buildVideoLink } from 'src/assets/player/utils'
import { Injectable } from '@angular/core'
+import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
import {
COMPLETE_RULES,
ENHANCED_RULES,
return this.render({ name: 'customPageMarkdownIt', markdown, withEmoji: true, additionalAllowedTags })
}
- processVideoTimestamps (html: string) {
+ processVideoTimestamps (videoShortUUID: string, html: string) {
return html.replace(/((\d{1,2}):)?(\d{1,2}):(\d{1,2})/g, function (str, _, h, m, s) {
const t = (3600 * +(h || 0)) + (60 * +(m || 0)) + (+(s || 0))
- const url = buildVideoLink({ startTime: t })
+
+ const url = decorateVideoLink({
+ url: buildVideoLink({ shortUUID: videoShortUUID }),
+ startTime: t
+ })
return `<a class="video-timestamp" href="${url}">${str}</a>`
})
}
import { Injectable } from '@angular/core'
import { Router } from '@angular/router'
import { dateToHuman } from '@app/helpers'
-import { ResultList } from '@shared/models'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode, ResultList } from '@shared/models'
@Injectable()
export class RestExtractor {
import { DatePipe } from '@angular/common'
import { HttpErrorResponse } from '@angular/common/http'
import { Notifier } from '@app/core'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
import { environment } from '../../environments/environment'
import { AuthService } from '../core/auth'
+++ /dev/null
-import { AbstractControl, FormControl, ValidatorFn, Validators } from '@angular/forms'
-import { BuildFormValidator } from './form-validator.model'
-import { validateHost } from './host'
-
-export function getNotEmptyHosts (hosts: string) {
- return hosts
- .split('\n')
- .filter((host: string) => host && host.length !== 0) // Eject empty hosts
-}
-
-const validDomains: ValidatorFn = (control: FormControl) => {
- if (!control.value) return null
-
- const newHostsErrors = []
- const hosts = getNotEmptyHosts(control.value)
-
- for (const host of hosts) {
- if (validateHost(host) === false) {
- newHostsErrors.push($localize`${host} is not valid`)
- }
- }
-
- /* Is not valid. */
- if (newHostsErrors.length !== 0) {
- return {
- 'validDomains': {
- reason: 'invalid',
- value: newHostsErrors.join('. ') + '.'
- }
- }
- }
-
- /* Is valid. */
- return null
-}
-
-const isHostsUnique: ValidatorFn = (control: AbstractControl) => {
- if (!control.value) return null
-
- const hosts = getNotEmptyHosts(control.value)
-
- if (hosts.every((host: string) => hosts.indexOf(host) === hosts.lastIndexOf(host))) {
- return null
- } else {
- return {
- 'uniqueDomains': {
- reason: 'invalid'
- }
- }
- }
-}
-
-export const DOMAINS_VALIDATOR: BuildFormValidator = {
- VALIDATORS: [Validators.required, validDomains, isHostsUnique],
- MESSAGES: {
- 'required': $localize`Domain is required.`,
- 'validDomains': $localize`Domains entered are invalid.`,
- 'uniqueDomains': $localize`Domains entered contain duplicates.`
- }
-}
--- /dev/null
+import { AbstractControl, ValidatorFn, Validators } from '@angular/forms'
+import { BuildFormValidator } from './form-validator.model'
+
+export function validateHost (value: string) {
+ // Thanks to http://stackoverflow.com/a/106223
+ const HOST_REGEXP = new RegExp(
+ '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
+ )
+
+ return HOST_REGEXP.test(value)
+}
+
+export function validateHandle (value: string) {
+ if (!value) return false
+
+ return value.includes('@')
+}
+
+const validHosts: ValidatorFn = (control: AbstractControl) => {
+ if (!control.value) return null
+
+ const errors = []
+ const hosts = splitAndGetNotEmpty(control.value)
+
+ for (const host of hosts) {
+ if (validateHost(host) === false) {
+ errors.push($localize`${host} is not valid`)
+ }
+ }
+
+ // valid
+ if (errors.length === 0) return null
+
+ return {
+ 'validHosts': {
+ reason: 'invalid',
+ value: errors.join('. ') + '.'
+ }
+ }
+}
+
+const validHostsOrHandles: ValidatorFn = (control: AbstractControl) => {
+ if (!control.value) return null
+
+ const errors = []
+ const lines = splitAndGetNotEmpty(control.value)
+
+ for (const line of lines) {
+ if (validateHost(line) === false && validateHandle(line) === false) {
+ errors.push($localize`${line} is not valid`)
+ }
+ }
+
+ // valid
+ if (errors.length === 0) return null
+
+ return {
+ 'validHostsOrHandles': {
+ reason: 'invalid',
+ value: errors.join('. ') + '.'
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+export function splitAndGetNotEmpty (value: string) {
+ return value
+ .split('\n')
+ .filter(line => line && line.length !== 0) // Eject empty hosts
+}
+
+export const unique: ValidatorFn = (control: AbstractControl) => {
+ if (!control.value) return null
+
+ const hosts = splitAndGetNotEmpty(control.value)
+
+ if (hosts.every((host: string) => hosts.indexOf(host) === hosts.lastIndexOf(host))) {
+ return null
+ }
+
+ return {
+ 'unique': {
+ reason: 'invalid'
+ }
+ }
+}
+
+export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = {
+ VALIDATORS: [ Validators.required, validHosts, unique ],
+ MESSAGES: {
+ 'required': $localize`Domain is required.`,
+ 'validHosts': $localize`Hosts entered are invalid.`,
+ 'unique': $localize`Hosts entered contain duplicates.`
+ }
+}
+
+export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = {
+ VALIDATORS: [ Validators.required, validHostsOrHandles, unique ],
+ MESSAGES: {
+ 'required': $localize`Domain is required.`,
+ 'validHostsOrHandles': $localize`Hosts or handles are invalid.`,
+ 'unique': $localize`Hosts or handles contain duplicates.`
+ }
+}
+++ /dev/null
-export function validateHost (value: string) {
- // Thanks to http://stackoverflow.com/a/106223
- const HOST_REGEXP = new RegExp(
- '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
- )
-
- return HOST_REGEXP.test(value)
-}
export * from './form-validator.model'
-export * from './host'
-// Don't re export const variables because webpack 4 cannot do tree shaking with them
+// Don't re export const variables because webpack cannot do tree shaking with them
// export * from './abuse-validators'
// export * from './batch-domains-validators'
// export * from './custom-config-validators'
import * as debug from 'debug'
import truncate from 'lodash-es/truncate'
import { SortMeta } from 'primeng/api'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main'
import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation'
import { VideoCommentService } from '@app/shared/shared-video-comment'
+import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils'
import { AbuseState, AdminAbuse } from '@shared/models'
import { AdvancedInputFilter } from '../shared-forms'
import { AbuseMessageModalComponent } from './abuse-message-modal.component'
getVideoEmbed (abuse: AdminAbuse) {
return buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: `${environment.originServerUrl}/videos/embed/${abuse.video.uuid}`,
+ decorateVideoLink({
+ url: buildVideoEmbedLink(abuse.video, environment.originServerUrl),
title: false,
warningTitle: false,
startTime: abuse.video.startAt,
-import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, ElementRef, Input, OnInit } from '@angular/core'
+import { buildPlaylistEmbedLink, buildVideoEmbedLink } from '@shared/core-utils'
import { CustomMarkupComponent } from './shared'
@Component({
ngOnInit () {
const link = this.type === 'video'
- ? buildVideoLink({ baseUrl: `${environment.originServerUrl}/videos/embed/${this.uuid}` })
- : buildPlaylistLink({ baseUrl: `${environment.originServerUrl}/video-playlists/embed/${this.uuid}` })
+ ? buildVideoEmbedLink({ uuid: this.uuid }, environment.originServerUrl)
+ : buildPlaylistEmbedLink({ uuid: this.uuid }, environment.originServerUrl)
this.el.nativeElement.innerHTML = buildVideoOrPlaylistEmbed(link, this.uuid)
}
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { SafeHtml } from '@angular/platform-browser'
import { MarkdownService, ScreenService } from '@app/core'
+import { Video } from '@shared/models'
@Component({
selector: 'my-markdown-textarea',
@Input() markdownType: 'text' | 'enhanced' = 'text'
@Input() customMarkdownRenderer?: (text: string) => Promise<string | HTMLElement>
- @Input() markdownVideo = false
+ @Input() markdownVideo: Video
@Input() name = 'description'
}
if (this.markdownVideo) {
- html = this.markdownService.processVideoTimestamps(html)
+ html = this.markdownService.processVideoTimestamps(this.markdownVideo.shortUUID, html)
}
return html
import { ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
-import { secondsToTime, timeToInt } from '../../../assets/player/utils'
+import { secondsToTime, timeToInt } from '@shared/core-utils'
@Component({
selector: 'my-timestamp-input',
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { RestExtractor, RestPagination, RestService } from '@app/core'
-import { ActivityPubActorType, ActorFollow, FollowState, ResultList } from '@shared/models'
+import { ActivityPubActorType, ActorFollow, FollowState, ResultList, ServerFollowCreate } from '@shared/models'
import { environment } from '../../../environments/environment'
@Injectable()
)
}
- follow (notEmptyHosts: string[]) {
- const body = {
- hosts: notEmptyHosts
+ follow (hostsOrHandles: string[]) {
+ const body: ServerFollowCreate = {
+ handles: hostsOrHandles.filter(v => v.includes('@')),
+ hosts: hostsOrHandles.filter(v => !v.includes('@'))
}
return this.authHttp.post(InstanceFollowService.BASE_APPLICATION_URL + '/following', body)
}
unfollow (follow: ActorFollow) {
- return this.authHttp.delete(InstanceFollowService.BASE_APPLICATION_URL + '/following/' + follow.following.host)
+ const handle = follow.following.name + '@' + follow.following.host
+
+ return this.authHttp.delete(InstanceFollowService.BASE_APPLICATION_URL + '/following/' + handle)
.pipe(
map(this.restExtractor.extractDataBool),
catchError(res => this.restExtractor.handleError(res))
import { Observable, of, throwError as observableThrowError } from 'rxjs'
import { catchError, switchMap } from 'rxjs/operators'
-import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse } from '@angular/common/http'
+import { HTTP_INTERCEPTORS, HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'
import { Injectable, Injector } from '@angular/core'
-import { AuthService } from '@app/core/auth/auth.service'
import { Router } from '@angular/router'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { OAuth2ErrorCode, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models/server'
+import { AuthService } from '@app/core/auth/auth.service'
+import { HttpStatusCode } from '@shared/models'
+import { OAuth2ErrorCode, PeerTubeProblemDocument } from '@shared/models/server'
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
comment?: {
threadId: number
- video: {
- id: number
- uuid: string
- name: string
- }
+ video: VideoInfo
}
account?: ActorInfo
import { Subject } from 'rxjs'
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
import { ComponentPagination, hasMoreItems, Notifier } from '@app/core'
-import { UserNotificationType, AbuseState } from '@shared/models'
+import { AbuseState } from '@shared/models'
import { UserNotification } from './user-notification.model'
import { UserNotificationService } from './user-notification.service'
import { User } from '@app/core/users/user.model'
import { durationToString, getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers'
import { Actor } from '@app/shared/shared-main/account/actor.model'
+import { buildVideoWatchPath } from '@shared/core-utils'
import { peertubeTranslate } from '@shared/core-utils/i18n'
import {
ActorImage,
pluginData?: any
static buildWatchUrl (video: Partial<Pick<Video, 'uuid' | 'shortUUID'>>) {
- return '/w/' + (video.shortUUID || video.uuid)
+ return buildVideoWatchPath({ shortUUID: video.shortUUID || video.uuid })
}
static buildUpdateUrl (video: Pick<Video, 'uuid'>) {
<ng-template #modal>
<div class="modal-header">
- <h4 i18n class="modal-title">{{ action }}</h4>
+ <h4 class="modal-title">{{ action }}</h4>
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
</div>
<label i18n for="hosts">1 host (without "http://") per line</label>
<textarea
- [placeholder]="placeholder" formControlName="domains" type="text" id="hosts" name="hosts"
- class="form-control" [ngClass]="{ 'input-error': formErrors['domains'] }" ngbAutofocus
+ [placeholder]="placeholder" formControlName="hosts" type="text" id="hosts" name="hosts"
+ class="form-control" [ngClass]="{ 'input-error': formErrors['hosts'] }" ngbAutofocus
></textarea>
- <div *ngIf="formErrors.domains" class="form-error">
- {{ formErrors.domains }}
+ <div *ngIf="formErrors.hosts" class="form-error">
+ {{ formErrors.hosts }}
- <div *ngIf="form.controls['domains'].errors.validDomains">
- {{ form.controls['domains'].errors.validDomains.value }}
+ <div *ngIf="form.controls['hosts'].errors.validHosts">
+ {{ form.controls['hosts'].errors.validHosts.value }}
</div>
</div>
</div>
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
-import { DOMAINS_VALIDATOR, getNotEmptyHosts } from '../form-validators/batch-domains-validators'
+import { splitAndGetNotEmpty, UNIQUE_HOSTS_VALIDATOR } from '../form-validators/host-validators'
@Component({
selector: 'my-batch-domains-modal',
if (!this.action) this.action = $localize`Process domains`
this.buildForm({
- domains: DOMAINS_VALIDATOR
+ hosts: UNIQUE_HOSTS_VALIDATOR
})
}
}
submit () {
- this.domains.emit(
- getNotEmptyHosts(this.form.controls['domains'].value)
- )
+ this.domains.emit(splitAndGetNotEmpty(this.form.controls['hosts'].value))
this.form.reset()
this.hide()
}
import { mapValues, pickBy } from 'lodash-es'
-import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
+import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
import { Notifier } from '@app/core'
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
+import { decorateVideoLink } from '@shared/core-utils'
import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
import { AbusePredefinedReasonsString } from '@shared/models'
import { Video } from '../../shared-main'
getVideoEmbed () {
return this.sanitizer.bypassSecurityTrustHtml(
buildVideoOrPlaylistEmbed(
- buildVideoLink({
- baseUrl: this.video.embedUrl,
+ decorateVideoLink({
+ url: this.video.embedUrl,
title: false,
warningTitle: false
}),
+
this.video.name
)
)
-import { BooleanBothQuery, BooleanQuery, SearchTargetType, VideosSearchQuery } from '@shared/models'
+import {
+ BooleanBothQuery,
+ BooleanQuery,
+ SearchTargetType,
+ VideoChannelsSearchQuery,
+ VideoPlaylistsSearchQuery,
+ VideosSearchQuery
+} from '@shared/models'
export class AdvancedSearch {
startDate: string // ISO 8601
isLive: BooleanQuery
+ host: string
+
sort: string
searchTarget: SearchTargetType
isLive?: BooleanQuery
+ host?: string
+
durationMin?: string
durationMax?: string
sort?: string
this.durationMin = parseInt(options.durationMin, 10)
this.durationMax = parseInt(options.durationMax, 10)
+ this.host = options.host || undefined
+
this.searchTarget = options.searchTarget || undefined
if (isNaN(this.durationMin)) this.durationMin = undefined
this.durationMin = undefined
this.durationMax = undefined
this.isLive = undefined
+ this.host = undefined
this.sort = '-match'
}
durationMin: this.durationMin,
durationMax: this.durationMax,
isLive: this.isLive,
+ host: this.host,
sort: this.sort,
searchTarget: this.searchTarget
}
}
- toAPIObject (): VideosSearchQuery {
+ toVideosAPIObject (): VideosSearchQuery {
let isLive: boolean
if (this.isLive) isLive = this.isLive === 'true'
tagsAllOf: this.tagsAllOf,
durationMin: this.durationMin,
durationMax: this.durationMax,
+ host: this.host,
isLive,
sort: this.sort,
searchTarget: this.searchTarget
}
}
+ toPlaylistAPIObject (): VideoPlaylistsSearchQuery {
+ return {
+ host: this.host,
+ searchTarget: this.searchTarget
+ }
+ }
+
+ toChannelAPIObject (): VideoChannelsSearchQuery {
+ return {
+ host: this.host,
+ searchTarget: this.searchTarget
+ }
+ }
+
size () {
let acc = 0
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
import {
ResultList,
- SearchTargetType,
Video as VideoServerModel,
VideoChannel as VideoChannelServerModel,
VideoPlaylist as VideoPlaylistServerModel
}
searchVideos (parameters: {
- search: string,
- componentPagination?: ComponentPaginationLight,
+ search: string
+ componentPagination?: ComponentPaginationLight
advancedSearch?: AdvancedSearch
}): Observable<ResultList<Video>> {
const { search, componentPagination, advancedSearch } = parameters
if (search) params = params.append('search', search)
if (advancedSearch) {
- const advancedSearchObject = advancedSearch.toAPIObject()
+ const advancedSearchObject = advancedSearch.toVideosAPIObject()
params = this.restService.addObjectParams(params, advancedSearchObject)
}
}
searchVideoChannels (parameters: {
- search: string,
- searchTarget?: SearchTargetType,
+ search: string
+ advancedSearch?: AdvancedSearch
componentPagination?: ComponentPaginationLight
}): Observable<ResultList<VideoChannel>> {
- const { search, componentPagination, searchTarget } = parameters
+ const { search, advancedSearch, componentPagination } = parameters
const url = SearchService.BASE_SEARCH_URL + 'video-channels'
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination)
- params = params.append('search', search)
- if (searchTarget) {
- params = params.append('searchTarget', searchTarget as string)
+ if (search) params = params.append('search', search)
+
+ if (advancedSearch) {
+ const advancedSearchObject = advancedSearch.toChannelAPIObject()
+ params = this.restService.addObjectParams(params, advancedSearchObject)
}
return this.authHttp
}
searchVideoPlaylists (parameters: {
- search: string,
- searchTarget?: SearchTargetType,
+ search: string
+ advancedSearch?: AdvancedSearch
componentPagination?: ComponentPaginationLight
}): Observable<ResultList<VideoPlaylist>> {
- const { search, componentPagination, searchTarget } = parameters
+ const { search, advancedSearch, componentPagination } = parameters
const url = SearchService.BASE_SEARCH_URL + 'video-playlists'
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination)
- params = params.append('search', search)
- if (searchTarget) {
- params = params.append('searchTarget', searchTarget as string)
+ if (search) params = params.append('search', search)
+
+ if (advancedSearch) {
+ const advancedSearchObject = advancedSearch.toPlaylistAPIObject()
+ params = this.restService.addObjectParams(params, advancedSearchObject)
}
return this.authHttp
import { Component, ElementRef, Input, ViewChild } from '@angular/core'
-import { Video, VideoDetails } from '@app/shared/shared-main'
+import { VideoDetails } from '@app/shared/shared-main'
import { VideoPlaylist } from '@app/shared/shared-video-playlist'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { buildPlaylistLink, buildVideoLink, decoratePlaylistLink, decorateVideoLink } from '@shared/core-utils'
import { VideoCaption } from '@shared/models'
-import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from '../../../assets/player/utils'
+import { buildVideoOrPlaylistEmbed } from '../../../assets/player/utils'
type Customizations = {
startAtCheckbox: boolean
}
getVideoIframeCode () {
- const options = this.getVideoOptions(this.video.embedUrl)
+ const embedUrl = decorateVideoLink({ url: this.video.embedUrl, ...this.getVideoOptions() })
- const embedUrl = buildVideoLink(options)
return buildVideoOrPlaylistEmbed(embedUrl, this.video.name)
}
getPlaylistIframeCode () {
- const options = this.getPlaylistOptions(this.playlist.embedUrl)
+ const embedUrl = decoratePlaylistLink({ url: this.playlist.embedUrl, ...this.getPlaylistOptions() })
- const embedUrl = buildPlaylistLink(options)
return buildVideoOrPlaylistEmbed(embedUrl, this.playlist.displayName)
}
getVideoUrl () {
- let baseUrl = this.customizations.originUrl ? this.video.originInstanceUrl : window.location.origin
- baseUrl += Video.buildWatchUrl(this.video)
+ const baseUrl = this.customizations.originUrl
+ ? this.video.originInstanceUrl
+ : window.location.origin
- const options = this.getVideoOptions(baseUrl)
+ return decorateVideoLink({
+ url: buildVideoLink(this.video, baseUrl),
- return buildVideoLink(options)
+ ...this.getVideoOptions()
+ })
}
getPlaylistUrl () {
- const base = window.location.origin + VideoPlaylist.buildWatchUrl(this.playlist)
+ const url = buildPlaylistLink(this.playlist)
+ if (!this.includeVideoInPlaylist) return url
- if (!this.includeVideoInPlaylist) return base
-
- return base + '?playlistPosition=' + this.playlistPosition
+ return decoratePlaylistLink({ url, playlistPosition: this.playlistPosition })
}
notSecure () {
}
}
- private getVideoOptions (baseUrl?: string) {
+ private getVideoOptions () {
return {
- baseUrl,
-
startTime: this.customizations.startAtCheckbox ? this.customizations.startAt : undefined,
stopTime: this.customizations.stopAtCheckbox ? this.customizations.stopAt : undefined,
} from '@app/core'
import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
import { GlobalIconName } from '@app/shared/shared-icons'
-import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils/miscs/date'
+import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils'
import { HTMLServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/models'
import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
import { Syndication, Video } from '../shared-main'
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
import { AuthService, DisableForReuseHook, Notifier } from '@app/core'
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
+import { secondsToTime } from '@shared/core-utils'
import {
Video,
VideoExistInPlaylist,
VideoPlaylistElementUpdate,
VideoPlaylistPrivacy
} from '@shared/models'
-import { secondsToTime } from '../../../assets/player/utils'
import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators'
import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service'
import { AuthService, Notifier, ServerService } from '@app/core'
import { Video } from '@app/shared/shared-main'
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
+import { secondsToTime } from '@shared/core-utils'
import { HTMLServerConfig, VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models'
-import { secondsToTime } from '../../../assets/player/utils'
import { VideoPlaylistElement } from './video-playlist-element.model'
import { VideoPlaylist } from './video-playlist.model'
import { VideoPlaylistService } from './video-playlist.service'
import { getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers'
import { Actor } from '@app/shared/shared-main'
+import { buildPlaylistWatchPath } from '@shared/core-utils'
import { peertubeTranslate } from '@shared/core-utils/i18n'
import {
AccountSummary,
videoChannelBy?: string
static buildWatchUrl (playlist: Pick<VideoPlaylist, 'uuid' | 'shortUUID'>) {
- return '/w/p/' + (playlist.shortUUID || playlist.uuid)
+ return buildPlaylistWatchPath({ shortUUID: playlist.shortUUID || playlist.uuid })
}
constructor (hash: ServerVideoPlaylist, translations: {}) {
import { Events, Segment } from 'p2p-media-loader-core'
import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs'
import videojs from 'video.js'
+import { timeToInt } from '@shared/core-utils'
import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../peertube-videojs-typings'
-import { timeToInt } from '../utils'
import { registerConfigPlugin, registerSourceHandler } from './hls-plugin'
registerConfigPlugin(videojs)
import './playlist/playlist-plugin'
import videojs from 'video.js'
import { PluginsManager } from '@root-helpers/plugins-manager'
+import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
import { isDefaultLocale } from '@shared/core-utils/i18n'
import { VideoFile } from '@shared/models'
import { copyToClipboard } from '../../root-helpers/utils'
import {
NextPreviousVideoButtonOptions,
P2PMediaLoaderPluginOptions,
+ PeerTubeLinkButtonOptions,
PlaylistPluginOptions,
UserWatching,
VideoJSCaption,
VideoJSPluginOptions
} from './peertube-videojs-typings'
import { TranslationsManager } from './translations-manager'
-import { buildVideoLink, buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils'
+import { buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
(videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed'
videoCaptions: VideoJSCaption[]
videoUUID: string
+ videoShortUUID: string
userWatching?: UserWatching
PeertubePlayerManager.alreadyPlayed = true
})
- self.addContextMenu(mode, player, options.common.embedUrl, options.common.embedTitle)
+ self.addContextMenu({
+ mode,
+ player,
+ videoShortUUID: options.common.videoShortUUID,
+ videoEmbedUrl: options.common.embedUrl,
+ videoEmbedTitle: options.common.embedTitle
+ })
player.bezels()
player.stats({
videojs(newVideoElement, videojsOptions, function (this: videojs.Player) {
const player = this
- self.addContextMenu(mode, player, options.common.embedUrl, options.common.embedTitle)
+ self.addContextMenu({
+ mode,
+ player,
+ videoShortUUID: options.common.videoShortUUID,
+ videoEmbedUrl: options.common.embedUrl,
+ videoEmbedTitle: options.common.embedTitle
+ })
PeertubePlayerManager.onPlayerChange(player)
})
controlBar: {
children: this.getControlBarChildren(mode, {
+ videoShortUUID: commonOptions.videoShortUUID,
+
captions: commonOptions.captions,
peertubeLink: commonOptions.peertubeLink,
theaterButton: commonOptions.theaterButton,
}
private static getControlBarChildren (mode: PlayerMode, options: {
+ videoShortUUID: string
+
peertubeLink: boolean
theaterButton: boolean
captions: boolean
if (options.peertubeLink === true) {
Object.assign(children, {
- 'peerTubeLinkButton': {}
+ 'peerTubeLinkButton': { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions
})
}
return children
}
- private static addContextMenu (mode: PlayerMode, player: videojs.Player, videoEmbedUrl: string, videoEmbedTitle: string) {
+ private static addContextMenu (options: {
+ mode: PlayerMode
+ player: videojs.Player
+ videoShortUUID: string
+ videoEmbedUrl: string
+ videoEmbedTitle: string
+ }) {
+ const { mode, player, videoEmbedTitle, videoEmbedUrl, videoShortUUID } = options
+
const content = () => {
const isLoopEnabled = player.options_['loop']
const items = [
{
label: player.localize('Copy the video URL'),
listener: function () {
- copyToClipboard(buildVideoLink())
+ copyToClipboard(buildVideoLink({ shortUUID: videoShortUUID }))
}
},
{
label: player.localize('Copy the video URL at the current time'),
listener: function (this: videojs.Player) {
- copyToClipboard(buildVideoLink({ startTime: this.currentTime() }))
+ const url = buildVideoLink({ shortUUID: videoShortUUID })
+
+ copyToClipboard(decorateVideoLink({ url, startTime: this.currentTime() }))
}
},
{
-import videojs from 'video.js'
import './videojs-components/settings-menu-button'
-import {
- PeerTubePluginOptions,
- ResolutionUpdateData,
- UserWatching,
- VideoJSCaption
-} from './peertube-videojs-typings'
-import { isMobile, timeToInt } from './utils'
+import videojs from 'video.js'
+import { timeToInt } from '@shared/core-utils'
import {
getStoredLastSubtitle,
getStoredMute,
saveVideoWatchHistory,
saveVolumeInStore
} from './peertube-player-local-storage'
+import { PeerTubePluginOptions, ResolutionUpdateData, UserWatching, VideoJSCaption } from './peertube-videojs-typings'
+import { isMobile } from './utils'
const Plugin = videojs.getPlugin('plugin')
isDisabled: () => boolean
}
+type PeerTubeLinkButtonOptions = {
+ shortUUID: string
+}
+
type WebtorrentPluginOptions = {
playerElement: HTMLVideoElement
VideoJSPluginOptions,
LoadedQualityData,
QualityLevelRepresentation,
+ PeerTubeLinkButtonOptions,
QualityLevels
}
import videojs from 'video.js'
+import { secondsToTime } from '@shared/core-utils'
import { VideoPlaylistElement } from '@shared/models'
import { PlaylistItemOptions } from '../peertube-videojs-typings'
-import { secondsToTime } from '../utils'
const Component = videojs.getComponent('Component')
import videojs from 'video.js'
+import { secondsToTime } from '@shared/core-utils'
import { PlayerNetworkInfo as EventPlayerNetworkInfo } from '../peertube-videojs-typings'
-import { bytes, secondsToTime } from '../utils'
+import { bytes } from '../utils'
interface StatsCardOptions extends videojs.ComponentOptions {
videoUUID: string
-import { VideoFile } from '@shared/models'
import { escapeHTML } from '@shared/core-utils/renderer'
+import { VideoFile } from '@shared/models'
function toTitleCase (str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
}
-function buildVideoLink (options: {
- baseUrl?: string
-
- startTime?: number
- stopTime?: number
-
- subtitle?: string
-
- loop?: boolean
- autoplay?: boolean
- muted?: boolean
-
- // Embed options
- title?: boolean
- warningTitle?: boolean
- controls?: boolean
- peertubeLink?: boolean
-} = {}) {
- const { baseUrl } = options
-
- const url = baseUrl
- ? baseUrl
- : window.location.origin + window.location.pathname.replace('/videos/embed/', '/w/')
-
- const params = generateParams(window.location.search)
-
- if (options.startTime !== undefined && options.startTime !== null) {
- const startTimeInt = Math.floor(options.startTime)
- params.set('start', secondsToTime(startTimeInt))
- }
-
- if (options.stopTime) {
- const stopTimeInt = Math.floor(options.stopTime)
- params.set('stop', secondsToTime(stopTimeInt))
- }
-
- if (options.subtitle) params.set('subtitle', options.subtitle)
-
- if (options.loop === true) params.set('loop', '1')
- if (options.autoplay === true) params.set('autoplay', '1')
- if (options.muted === true) params.set('muted', '1')
- if (options.title === false) params.set('title', '0')
- if (options.warningTitle === false) params.set('warningTitle', '0')
- if (options.controls === false) params.set('controls', '0')
- if (options.peertubeLink === false) params.set('peertubeLink', '0')
-
- return buildUrl(url, params)
-}
-
-function buildPlaylistLink (options: {
- baseUrl?: string
-
- playlistPosition?: number
-}) {
- const { baseUrl } = options
-
- const url = baseUrl
- ? baseUrl
- : window.location.origin + window.location.pathname.replace('/video-playlists/embed/', '/w/p/')
-
- const params = generateParams(window.location.search)
-
- if (options.playlistPosition) params.set('playlistPosition', '' + options.playlistPosition)
-
- return buildUrl(url, params)
-}
-
-function buildUrl (url: string, params: URLSearchParams) {
- let hasParams = false
- params.forEach(() => hasParams = true)
-
- if (hasParams) return url + '?' + params.toString()
-
- return url
-}
-
-function generateParams (url: string) {
- const params = new URLSearchParams(window.location.search)
- // Unused parameters in embed
- params.delete('videoId')
- params.delete('resume')
-
- return params
-}
-
-function timeToInt (time: number | string) {
- if (!time) return 0
- if (typeof time === 'number') return time
-
- const reg = /^((\d+)[h:])?((\d+)[m:])?((\d+)s?)?$/
- const matches = time.match(reg)
-
- if (!matches) return 0
-
- const hours = parseInt(matches[2] || '0', 10)
- const minutes = parseInt(matches[4] || '0', 10)
- const seconds = parseInt(matches[6] || '0', 10)
-
- return hours * 3600 + minutes * 60 + seconds
-}
-
-function secondsToTime (seconds: number, full = false, symbol?: string) {
- let time = ''
-
- if (seconds === 0 && !full) return '0s'
-
- const hourSymbol = (symbol || 'h')
- const minuteSymbol = (symbol || 'm')
- const secondsSymbol = full ? '' : 's'
-
- const hours = Math.floor(seconds / 3600)
- if (hours >= 1) time = hours + hourSymbol
- else if (full) time = '0' + hourSymbol
-
- seconds %= 3600
- const minutes = Math.floor(seconds / 60)
- if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol
- else if (minutes >= 1) time += minutes + minuteSymbol
- else if (full) time += '00' + minuteSymbol
-
- seconds %= 60
- if (seconds >= 1 && seconds < 10 && full) time += '0' + seconds + secondsSymbol
- else if (seconds >= 1) time += seconds + secondsSymbol
- else if (full) time += '00'
-
- return time
-}
-
function buildVideoOrPlaylistEmbed (embedUrl: string, embedTitle: string) {
const title = escapeHTML(embedTitle)
+
return '<iframe width="560" height="315" ' +
'sandbox="allow-same-origin allow-scripts allow-popups" ' +
'title="' + title + '" ' +
export {
getRtcConfig,
toTitleCase,
- timeToInt,
- secondsToTime,
isWebRTCDisabled,
- buildPlaylistLink,
- buildVideoLink,
+
buildVideoOrPlaylistEmbed,
videoFileMaxByResolution,
videoFileMinByResolution,
-import { buildVideoLink } from '../utils'
import videojs from 'video.js'
+import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
+import { PeerTubeLinkButtonOptions } from '../peertube-videojs-typings'
const Button = videojs.getComponent('Button')
class PeerTubeLinkButton extends Button {
+ private shortUUID: string
- constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
- super(player, options)
+ constructor (player: videojs.Player, options?: PeerTubeLinkButtonOptions) {
+ super(player, options as any)
+
+ this.shortUUID = options.shortUUID
}
createEl () {
}
updateHref () {
- this.el().setAttribute('href', buildVideoLink({ startTime: this.player().currentTime() }))
+ this.el().setAttribute('href', this.buildLink())
}
handleClick () {
private buildElement () {
const el = videojs.dom.createEl('a', {
- href: buildVideoLink(),
+ href: this.buildLink(),
innerHTML: 'PeerTube',
title: this.player().localize('Video page (new window)'),
className: 'vjs-peertube-link',
return el as HTMLButtonElement
}
+
+ private buildLink () {
+ const url = buildVideoLink({ shortUUID: this.shortUUID })
+
+ return decorateVideoLink({ url, startTime: this.player().currentTime() })
+ }
}
videojs.registerComponent('PeerTubeLinkButton', PeerTubeLinkButton)
import videojs from 'video.js'
import * as WebTorrent from 'webtorrent'
-import { renderVideo } from './video-renderer'
-import { LoadedQualityData, PlayerNetworkInfo, WebtorrentPluginOptions } from '../peertube-videojs-typings'
-import { getRtcConfig, timeToInt, videoFileMaxByResolution, videoFileMinByResolution, isIOS, isSafari } from '../utils'
-import { PeertubeChunkStore } from './peertube-chunk-store'
+import { timeToInt } from '@shared/core-utils'
+import { VideoFile } from '@shared/models'
import {
getAverageBandwidthInStore,
getStoredMute,
getStoredVolume,
saveAverageBandwidth
} from '../peertube-player-local-storage'
-import { VideoFile } from '@shared/models'
+import { LoadedQualityData, PlayerNetworkInfo, WebtorrentPluginOptions } from '../peertube-videojs-typings'
+import { getRtcConfig, isIOS, videoFileMaxByResolution, videoFileMinByResolution } from '../utils'
+import { PeertubeChunkStore } from './peertube-chunk-store'
+import { renderVideo } from './video-renderer'
const CacheChunkStore = require('cache-chunk-store')
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">سجل مشاهداتي</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target>حصة الفيديو</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>غير محدود <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> في اليوم الواحد)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">الفديرالية</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target>لِج</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="2308975396733519902" datatype="html">
<source>Create an account</source>
<target>أنشئ حسابًا</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="8936704404804793618" datatype="html">
<source>Videos</source>
<target>الفيديوهات</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target>الفيديوهات</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">هذا خطأ.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">هذا الملف كبير. اتصل بالمدير حتى يزيد حد الرفع.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="2468689683507870964" datatype="html">
<source>In this instance's network</source>
<target state="translated">في شبكة هذ المثيل</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="4209525355702493436" datatype="html">
<source>Ban</source>
<target>احظر</target>
<target state="translated">فيديو\تعليق\حساب</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target>مقبض تابع</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="3301856295120048857" datatype="html">
<source>State <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target>حالة <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<target>يعرض <x id="INTERPOLATION"/> ل <x id="INTERPOLATION_1"/> من <x id="INTERPOLATION_2"/> متابع</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">المثلاء المتابَعون</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target>المضيف</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">ألغ المتابعة</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target>افتح مثيل الخادم في لسان جديد</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target>لم يُعثر على مضيف مطابق للمرشحات الحالية.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target>مثيل الخادم الخاص بك لا يتابع أي شخص.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target>يعرض <x id="INTERPOLATION"/> ل <x id="INTERPOLATION_1"/> من <x id="INTERPOLATION_2"/> مضيفا</target>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target>يبدو أنك لست على خادم HTTPS. يحتاج خادم الويب الخاص بك إلى تنشيط TLS لمتابعة الخوادم.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target>تابع النطاق</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5674286808255988565" datatype="html">
<source>Create</source>
<target>إنشاء</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="8147229944654164397" datatype="html">
<source>{VAR_PLURAL, plural, =1 {Video} other {Videos} }</source>
<target>{VAR_PLURAL, plural, =1 {فيديو} other {مقاطع فيديو} }</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target>اسم المستخدم</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">مثل jane_doe</target>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target>البريد الإلكتروني</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="6475711663580561164" datatype="html">
<source>mail@example.com</source>
<target>mail@example.com</target>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
<target>كلمة المرور</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8371296837649897723" datatype="html">
<source>If you leave the password empty, an email will be sent to the user.</source>
<target>إذا تركت كلمة المرور فارغة ، فسيتم إرسال بريد إلكتروني إلى المستخدم.</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="translated">الدور</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">تحويل الترميز مفعل. سيقتطع الحجم <x id="START_TAG_STRONG"/>الأصلي<x id="CLOSE_TAG_STRONG"/> للفيديو من حصة الفيديو.<x id="LINE_BREAK"/>يمكن لهذا المستخدم رفع ~ <x id="INTERPOLATION"/> كحد أقصى. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">بدون (استيثاق محلي)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target>يعرض <x id="INTERPOLATION"/> ل <x id="INTERPOLATION_1"/> من <x id="INTERPOLATION_2"/> إبلغا</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">6</context></context-group>
</trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">منصات تتابعك</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
<trans-unit id="3109314382334906782" datatype="html">
<source>Reportee</source>
<target>مراسل</target>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target>فيديو</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">ترجمات</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">أتريد حذف <x id="PH"/>؟ ستحذف جميع فيديوهات قناة <x id="PH_1"/>، ولن تتمكن من إنشاء قناة بنفس الاسم (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="4302331889176439801" datatype="html">
<source>Request email for account verification</source>
<target>طلب البريد الإلكتروني للتحقق من الحساب</target>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target>عنوان البريد الإلكتروني</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4027779086550572813" datatype="html">
<source>Send verification email</source>
<target>إرسال رسالة التأكيد</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="6479885129995567639" datatype="html">
<source>Video channels</source>
<target>قنوات الفيديو</target>
<source>Username or email address</source>
<target>اسم المستخدم أو عنوان البريد الإلكتروني</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target>انقر هنا لإعادة تعيين كلمة المرور الخاصة بك</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target>أو قم بتسجيل الدخول باستخدام</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target>نسيتَ كلمة المرور</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target>عذرًا ، لا يمكنك استرداد كلمة المرور الخاصة بك لأن مدير مثيل الخادم الخاص بك لم يقم بتكوين نظام البريد الإلكتروني لبيرتيوب.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">عذرا، عُطلت خاصية الرفع في حسابك، اتصل بمدير المنصة ليقوم بفك قَفل حصتك.</target>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target>تم ارسال رسالتك.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target>لقد أرسلت هذا النموذج بالفعل مؤخرًا</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">فيديوهات الحساب</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target><x id="PH"/> متابعًا مباشرًا للحساب </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">بلِّغ عن هذا الحساب</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">فيديوهات</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target>تم نسخ اسم المستخدم</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">مشترك</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> مشتركا</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target>صوت فقط</target>
<source>Auto (via ffmpeg)</source>
<target>تلقائي (عبر ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<source><x id="PH"/> removed from instance followers </source>
<target>أُزيل <x id="PH"/> من متابعي المثيل </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target>تم إرسال طلب المتابعة!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>هل تريد الغاء متابعة <x id="PH"/>؟</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target>إلغاء المتابَعة</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target>انت لا تتابع <x id="PH"/> بعد الآن.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target>مفعّل</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target>خطأ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target>السجلات القياسية</target>
<target>حدّث كلمة مرور المستخدم</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">قائمة المتابَعين</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">قائمة المتابِعين</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target>حُدّث حساب المستخدم <x id="PH"/>.</target>
<target state="translated">الاتحادية</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">المثيلات المتابَعة</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">المثيلات المتابِعة</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">سيحذف مقاطع الفيديو ، ستحذف التعليقات.</target>
<target>تعيين البريد الإلكتروني كمتحقق منه</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target>اسم المستخدم أو كلمة المرور خاطئة.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">حسابك محجوب.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target>أُنشئت قناة الفيديو <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target>هذا الإسم موجود على هذا المثيل.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target>حُدثت قناة فيديو <x id="PH"/>.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-settings.component.ts</context><context context-type="linenumber">61</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>لتأكيد اكتب الاسم العلني لقناة الفيديو <x id="PH"/></target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target>حُذفت قناة فيديو <x id="PH"/>.</target>
<source>Ownership change request sent.</source>
<target>تم إرسال طلب تغيير الملكية.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target>الاشتراك في الحساب</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target>تم رفع الفيديو الخاص بك إلى حسابك وهو خاص.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>ولكن ستفقد البيانات المرتبطة (العلامات ،الوصف...) ، هل تريد بالتأكيد مغادرة هذه الصفحة؟</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>لم يرفع الفيديو الخاص بك حتى الآن ، هل تريد بالتأكيد مغادرة هذه الصفحة؟</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">رفع</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target>ارفع <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target>نُشر الفيديو.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>لم تحفظ التغييرات! إذا غادرت ، ستفقد التغييرات.</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">هذا الفيديو ليس متوفرا على هذا المثيل. هل تريد التوجه المثيل الأصلي: <a href="<x id="PH"/>"><x id="PH_1"/></a> ؟</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">اعادة توجيه</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>يحتوي هذا الفيديو على محتوى للبالغين أو محتوى صريح. أمتأكد من مشاهدته؟</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target>محتوى للبالغين أو محتوى صريح</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target>التالي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">ألغ</target>
<source>Autoplay is suspended</source>
<target>أُوقف التشغيل التلقائي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target>ادخل / اخرج من وضع ملء الشاشة (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target>شغل / أوقف مؤقتًا الفيديو (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target>أكتم / ألغ كتم الفيديو (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target>التخطي إلى نسبة مئوية من الفيديو: 0 هو 0٪ و 9 هو 90٪ (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target>زد مستوى الصوت (يتطلب تركيز اللاعب)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target>خفّض مستوى الصوت (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">البحث عن الفيديو (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">طلب الفيديو للخلف (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target>زيادة معدل التشغيل (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target>تقليل معدل التشغيل (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target>تصفح الفيديو إطار فإطار (يتطلب تركيز المشغل)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target>أعجبني الفيديو</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target>انتقل إلى اشتراكاتي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target>انتقل إلى فيديوهاتي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target>انتقل إلى مستورداتي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target>انتقل إلى قنواتي</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target>تحتاج لإعادة الإتصال.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target>اختصارات لوحة المفاتيح:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>أكثرت المحاولات، حاول لاحقا بعد <x id="PH"/> دقيقة.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target>أكثرت المحاولات، حاول لاحقا.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target>خطأ في السيرفر. يرجى إعادة المحاولة لاحقا.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="4670312387769733978" datatype="html">
<source>All unsaved data will be lost, are you sure you want to leave this page?</source>
<target>ستفقد جميع البيانات غير المحفوظة ، هل تريد مغادرة هذه الصفحة؟</target>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target>أخف</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target>طمس</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target>اعرض</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target>مجهول</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target>أي لغة</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="9178182467454450952" datatype="html">
<source>Confirm</source>
<target>أكد</target>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target>اسم النطاق مطلوب.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target>أسماء النطاقات المدخلة غير صالحة.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target>تحتوي المجالات المدخلة على تكرارات.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target><x id="PH"/> غير صالح </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="7784486624424057376" datatype="html">
<source>Instance name is required.</source>
<target>اسم مثيل الخادم مطلوب.</target>
<trans-unit id="187187500641108332" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Crea</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">El següent enllaç conté un token privat i no es deuria compartir amb cap persona.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">La seua cuota de vídeo s'excedeix amb aquest vídeo (tamany del vídeo: <x id="PH" equiv-text="videoSizeBytes"/>, utilitzat: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">La seua quota diària de vídeo s'excedeix amb aquest vídeo (tamany del vídeo: <x id="PH" equiv-text="videoSizeBytes"/>, utilitzat: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">subtítols</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Quota de vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="translated">Sense limit
<target state="translated">Federació</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Cancel·la</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="translated">Expulsa aquesta usuaria</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Aquesta instància permet el registre. No obstant aixó , tinga cura de comprovar les <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Condicions <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> <x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Condicions <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> abans de crear un compte. També pot buscar una altra instància que coincideixi amb les vostres necessitats: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/> <x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Usuari</target>
<source>Username or email address</source>
<target>Nom d'usuari o adreça de correu electrònic</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Contrasenya</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Premeu aquí per restablir la contrasenya</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">He oblidat la meua contrasenya</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Iniciar sessió amb un compte et permet publicar contingut</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Inicia sessió</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">O identifiqueu-vos amb</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Has oblidat la teva contrasenya</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">No podem recuperar la vostra contrasenya perquè l'administració de la vostra instància no ha configurat cap sistema de correus de PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Inseriu la vostra adreça de correu electrònic i us enviarem un enllaç per a restablir la contrasenya.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Correu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Adreça de correu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Restableix</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">en aquesta instància</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Registrar un compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="new">My videos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Sóc una tetera</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Això és un error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">El mitjà es massa gran per al servidor. Contacta amb l'administrador si desitja augmentar la grandària límit.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">CERCA GLOBAL</target>
<trans-unit id="9172233176401579786" datatype="html">
<source>Scheduled</source>
<target state="translated">Programat</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">192</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">192</context></context-group>
+ </trans-unit>
<trans-unit id="1435317307066082710" datatype="html">
<source>Hide the video until a specific date</source>
<target state="new">Hide the video until a specific date</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">193</context></context-group>
+ </trans-unit>
<trans-unit id="6148369758871787018" datatype="html">
<source>Video background image</source>
<target state="translated">Imatge de fons del vídeo</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Estat</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Amfitrió</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="8286337167859377104">
<source>Create user</source>
<target>Afegeix un usuari</target>
-
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">93</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.html</context><context context-type="linenumber">20</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">93</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.html</context><context context-type="linenumber">20</context></context-group>
+ </trans-unit>
<trans-unit id="8363291180171434623" datatype="html">
<source>Table parameters</source>
<target state="new">Table parameters</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nom d'usuari</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rol</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="new">This account does not have channels.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VÍDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Il·limitat</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> no és vàlid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Sol·licituds de seguiment enviades!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Realment vols deixar de seguir
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>No segueixis</target>
<target>Ja no segueixes a
<x id="PH"/> .
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target>Usuari
<x id="PH"/> creat.
</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">76</context></context-group>
+ </trans-unit>
<trans-unit id="8286337167859377104" datatype="html">
<source>Create user</source>
<target state="new">Create user</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target>Canal de vídeo
<x id="PH"/> creat.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Canal de vídeo
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Canal de vídeo
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Necessites tornar a connectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>La contrasenya s'ha restablit correctament!</target>
<target>Hi ha massa intents, torna-ho a provar després de
<x id="PH"/> minuts.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Hi ha massa intents, torna-ho a provar més tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Error del servidor. Torna-ho a intentar més tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Però es perdran les dades associades (etiquetes, descripció ...), estàs segur que vols deixar aquesta pàgina?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>El teu vídeo encara no s'ha carregat, estàs segur que vols sortir d'aquesta pàgina?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Puja
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vídeo publicat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="new">You have unsaved changes! If you leave, your changes will be lost.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Aquest vídeo conté contingut madur o explícit. Estàs segur que el vols veure?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Contingut madur o explícit</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Vytvořit</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Následující odkaz obsahuje soukromý token a neměl by být s nikým sdílen.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">Titulky</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Limit na videa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Zablokovat tohoto uživatele</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Uživatel</target>
<source>Username or email address</source>
<target>Uživatelské jméno nebo e-mail</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Heslo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Přihlásit</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Zapomenuté heslo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-mailová adresa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Vytvořit účet</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="new">My videos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Stav</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Uživatelské jméno</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Tento účet nemá žádné kanály.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Neomezeně</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> není platný
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Požadavek odeslán!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Opravdu chcete zrušit odběr kanálu <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Zrušit odběr</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Už dále neodebíráte <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Chyba</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Uživatel <x id="PH"/> aktualizován.</target>
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Videokanál <x id="PH"/> vytvořen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Videokanál <x id="PH"/> aktualizován.</target>
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Videokanál <x id="PH"/> odstraněn.</target>
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Odebírat účet</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Musíte se znovu připojit.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Vaše heslo bylo úspěšně resetováno!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Příliš mnoho pokusů, zkuste to prosím znovu za <x id="PH"/> minut.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Příliš mnoho pokusů, zkuste to prosím později.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Chyba serveru. Zkuste to prosím později.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Vaše video bylo nahráno na váš účet a je soukromé.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Ovšem přidružená data (štítky, popis...) budou ztraceny, opravdu chcete opustit tuto stránku?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Video ještě nebylo nahráno, opravdu chcete opustit tuto stránku?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video publikováno</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Máte neuložené změny! Pokud odejdete, budou vaše změny ztraceny.</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Toto video obsahuje citlivý materiál. Opravdu jej chcete přehrát?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Obsahuje citlivý materiál</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>To se mi líbí</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Min videohistorik</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="new">Video quota</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Bruger</target>
<source>Username or email address</source>
<target>Brugernavn eller email-adresse</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Adgangskode</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="new">Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Glemt din adgangskode</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Email-adresse</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>Opret en konto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Brugernavn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Do you really want to unfollow <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>Din video blev uploadet til din konto og er privat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Din video er ikke uploadet endnu, er du sikker på, at du vil forlade denne side?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video offentliggjort.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Mein Verlauf</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Erstellen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">Video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Der folgende Link enthält ein privates Token und sollte nicht an Dritte weitergegeben werden.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Ihr Videokontingent ist mit diesem Video überschritten (Videogröße: <x id="PH" equiv-text="videoSizeBytes"/>, verwendet: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, Kontingent: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Ihr tägliches Videokontingent wurde mit diesem Video überschritten (Videogröße: <x id="PH" equiv-text="videoSizeBytes"/>, verwendet: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, Kontingent: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">Untertitel</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Videokontingent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Unbegrenzt <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> pro Tag)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Föderation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Diesen Nutzer sperren</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Diese Instanz erlaubt eine Registrierung. Lesen sie sich trotzdem die <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Richtlinien<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Richtlinien<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>durch, bevor sie sich ein Konto erstellen. Hier können sie auch nach einer anderen Instanz suchen, die ihren Wünschen entspricht: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Diese Instanz erlaubt zurzeit keine Registrierung, sie können sich die <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Richtlinien<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> für mehr Details durchlesen, oder hier nach einer Instanz suchen, die Ihnen das Anlegen eines Kontos und das Hochladen von Videos erlaubt: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Benutzer</target>
<source>Username or email address</source>
<target>Benutzername oder E-Mail-Adresse</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Passwort</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Klicken Sie hier, um Ihr Passwort zurückzusetzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Ich habe mein Passwort vergessen</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Durch das Anmelden können sie Inhalte hochladen</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Anmelden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Oder anmelden mit</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Passwort vergessen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Es tut uns Leid, du kannst dein Kennwort nicht wiederherstellen weil dein Instanzadministrator das PeerTube-E-Mail-System nicht konfiguriert hat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Geben Sie Ihre E-Mail-Adresse ein und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-Mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-Mail-Adresse</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Zurücksetzen</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">auf dieser Instanz</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Konto erstellen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Meine Videos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Gleichzeitigkeit von Importaufträgen</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Ich bin ein Teekessel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Dies ist ein Fehler.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Das Medium ist zu groß für den Server. Bitte wenden Sie sich an Ihren Administrator, wenn Sie das Größenlimit erhöhen möchten.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Upload angehalten</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Entschuldigung, Ihr Account kann keine Videos hochladen. Wenn Sie Videos hochladen möchten, muss ein Administrator Ihr Videokontingent freischalten.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Folger-Identifikator</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Status</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundanz erlaubt <x id="START_TAG_P-SORTICON"/> <x id="CLOSE_TAG_P-SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Nichtmehr folgen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Öffne die Instanz in einem neuen Tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Kein Host für die aktuellen Filter gefunden.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Ihre Instanz folgt niemandem.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Zeige <x id="INTERPOLATION"/> bis <x id="INTERPOLATION_1"/> von <x id="INTERPOLATION_2"/> Ho</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Folge Domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Instanzen folgen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Aktion</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nutzername</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">z.B. max_mustermann</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Benutzerrolle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Transkodierung aktiviert. Das Videokontingent wird anhand der <x id="START_TAG_STRONG"/>originalen<x id="CLOSE_TAG_STRONG"/> Videogröße berechnet. <x id="LINE_BREAK"/> Dieser Nutzer kann maximal ~ <x id="INTERPOLATION"/> hochladen. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Auth-Plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Keine (lokale Authentifizierung)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Es sieht so aus, dass Ihr Server kein HTTPS verwendet. Auf Ihrem Webserver muss TLS aktiviert sein, damit Sie Servern folgen können.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Domains stummschalten</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">KANÄLE</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Dieses Konto hat keine Kanäle.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Wollen Sie wirklich <x id="PH" equiv-text="videoChannel.displayName"/> löschen? Es löscht <x id="PH_1" equiv-text="videoChannel.videosCount"/> Videos, die in diesem Kanal hochgeladen wurden, und Sie können keinen weiteren Kanal mit demselben Namen (<x id="PH_2" equiv-text="videoChannel.name"/>) erstellen!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target>Deine Nachricht wurde gesendet.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Du hast dieses Formular bereits kürzlich gesendet</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Videos des Kontos</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> direkte Kontofolgende </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Dieses Konto melden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOS</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>Benutzername kopiert</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 Abonnent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> Abonnenten</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Gefolgte Instanzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Folgende Instanzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Nur Ton</target>
<source>Auto (via ffmpeg)</source>
<target>Automatisch (über ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Domain wird benötigt.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Eingegebene Domains sind ungültig.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Eingegebene Domains enthalten Wiederholungen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Unbegrenzt</target>
<x id="PH"/> von den Instanzfolgern entfernt
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> ist ungültig
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Anfrage(n) zum Folgen gesendet!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Möchtest du <x id="PH"/> wirklich nicht mehr folgen?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Nicht mehr folgen</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Du folgst <x id="PH"/> nicht mehr.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>aktiviert</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Fehler</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Standard Log-Dateien</target>
<target>Benutzerkennwort geändert</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Liste aller Gefolgten</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Liste aller Follower</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Benutzer <x id="PH"/> aktualisiert.</target>
<target state="translated">Föderation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Gefolgte Instanzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Folgende Instanzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Videos werden gelöscht, Kommentare werden mit einem Grabstein markiert.</target>
<target>E-Mail als bestätigt setzen</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Videokanal <x id="PH"/> erstellt.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Dieser Name existiert bereits auf dieser Instanz.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Videokanal <x id="PH"/> aktualisiert.</target>
<target state="translated">Banner gelöscht.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Bitte gib zum Bestätigen den Anzeigenamen des Videokanals ( <x id="PH"/>) ein</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Videokanal <x id="PH"/> entfernt.</target>
<source>Ownership change request sent.</source>
<target>Eine Anfrage zur Änderung des Besitzers wurde versendet.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Diesen Account abonnieren</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">PLAYLISTS</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Gehe zu meinen Abos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Zu meinen Videos gehen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Gehe zu meinen Importen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Gehe zu meinen Kanälen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Referenzen des OAuth-Clients können nicht abgerufen werden: <x id="PH" equiv-text="error.text"/>. Stellen Sie sicher, dass PeerTube korrekt konfiguriert ist (Ordner config/), speziell der Abschnitt "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Bitte verbinde dich erneut.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Tastaturkürzel:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Falscher Benutzername oder falsches Passwort.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Ihr Konto wurde gesperrt.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">jede Sprache</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">verstecken</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">verwischen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">anzeigen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Unbekannt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Dein Passwort wurde zurückgesetzt!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Zu viele Versuche in kurzer Zeit. Bitte versuche es in <x id="PH"/> Minuten nochmal.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Zu viele Versuche in kurzer Zeit. Bitte versuche es später nochmal.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Server-Fehler. Bitte später erneut versuchen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Alle Kanäle von <x id="PH"/> abonniert. Du wirst über neue Videos darin benachrichtigt.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Das Video wurde in dein Konto hochgeladen und ist privat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Weitere Infos (Tags, Beschreibung, ...) werden verworfen, wenn du diese Seite verlässt. Bist du dir sicher?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Dein Video ist noch nicht hochgeladen. Willst du diese Seite wirklich verlassen?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Hochladen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>
<x id="PH"/> hochladen
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video veröffentlicht.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Es gibt ungespeicherte Änderungen! Wenn du die Seite verlässt, gehen die Änderungen verloren.</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Dieses Video ist auf dieser Instanz nicht verfügbar. Wollen Sie auf die Quellinstanz weitergeleitet werden: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Weiterleitung</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Dieses Video enthält Inhalte, die möglicherweise für bestimmte Zuschauer ungeeignet sind oder von diesen als anstößig empfunden werden. Möchtest du es wirklich ansehen?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Inhalt, der möglicherweise für bestimmte Zuschauer ungeeignet oder anstößig ist</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Nächstes</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Abbrechen</target>
<source>Autoplay is suspended</source>
<target state="translated">Autoplay ist unterbrochen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Vollbildmodus betreten/verlassen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Video abspielen/pausieren (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Video stummschalten/Stummschaltung aufheben (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Springe zu einem Prozentsatz des Videos: 0 entspricht 0%, 9 entspricht 90% (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Lautstärke erhöhen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Lautstärke verringern (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Vorspulen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Zurückspulen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Abspielgeschwindigkeit erhöhen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Abspielgeschwindigkeit verringern (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Einen Frame weitergehen (Player benötigt Fokus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Das Video gefällt mir</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Το ιστορικό μου</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">βίντεο</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Ο σύνδεσμος που ακολουθεί περιέχει απόρρητη συμβολοσειρά και δεν θα πρέπει να τον μοιραστείτε με τρίτους.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">υπότιτλοι</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Όριο βίντεο</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">ακόλουθοι</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Αποκλεισμός χρήστη</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Χρήστης</target>
<source>Username or email address</source>
<target>Όνομα χρήστη ή διεύθυνση e-mail</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Κωδικός σύνδεσης</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Ξέχασα τον κωδικό μου</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Σύνδεση</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Ή συνδεθείτε με:</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Ξεχάσατε τον κωδικό σύνδεσης</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Διεύθυνση e-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Επαναφορά</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<target>Δημιουργία λογαριασμού</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">ΒΙΝΤΕΟ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Αυτό είναι ένα σφάλμα.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Ψευδώνυμο (handle) ακολούθου</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Κατάσταση</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Κόμβος</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="translated">Αφαίρεση ακολούθησης</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Όνομα χρήστη</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Ρόλος</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Αυτός ο λογαριασμός δεν έχει κανάλια.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target>Το μήνυμά σας έχει σταλεί.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Στείλατε ήδη αυτή τη φόρμα πρόσφατα</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">ΒΙΝΤΕΟ</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>Το όνομα χρήστη αντιγράφτηκε</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target>Αυτόματα (με ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Απεριόριστα</target>
<x id="PH"/> διαγράφηκε από ακόλουθος του κόμβου
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> δεν είναι έγκυρο
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Τα αιτήματα ακολούθησης στάλθηκαν!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Θέλετε πραγματικά να σταματήσετε να ακολουθείτε το
<x id="PH"/>;
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Αφαίρεση ακολούθησης</target>
<target>Δεν ακολουθείτε το
<x id="PH"/> πια.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>ενεργοποιήθηκε</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Σφάλμα</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target>Ενημέρωση κωδικού χρήστη</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Το e-mail έχει επιβεβαιωθεί</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Δεν μπορείτε να αποκλείστε τον root.</target>
<target>Δημιουργήθηκε το κανάλι
<x id="PH"/>.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Το όνομα υπάρχει ήδη σ' αυτόν τον κόμβο</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Το κανάλι
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Παρακαλούμε πληκτρολογήστε το όνομα καναλιού του (
- <x id="PH"/>) για επιβεβαίωση
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Το κανάλι
<source>Ownership change request sent.</source>
<target>Το αίτημα αλλαγής κατόχου έχει σταλεί.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Συνδρομή στον λογαριασμό</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Μετάβαση στις συνδρομές μου</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Μετάβαση στα βίντεό μου</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Μετάβαση στις εισαγωγές μου</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Μετάβαση στα κανάλια μου</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Πρέπει να ξανασυνδεθείτε.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Συντομεύσεις πληκτρολογίου:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Λάθος όνομα χρήστη ή κωδικός.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Άγνωστο</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Ο κωδικός σας έχει ανανεωθεί με επιτυχία!</target>
<target>Πάρα πολλές προσπάθειες, δοκιμάστε ξανά μετά από
<x id="PH"/> λεπτά.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Πάρα πολλές προσπάθειες, δοκιμάστε ξανά αργότερα.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Σφάλμα κόμβου. Δοκιμάστε ξανά αργότερα.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>Το βίντεο ανέβηκε στον λογαριασμό σας και είναι ιδιωτικό.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Όμως οι σχετικές πληροφορίες (ετικέτες, περιγραφή...) θα χαθούν, σίγουρα θέλετε να φύγετε από τη σελίδα;</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Το βίντεο δεν έχει ανέβει ακόμα, θέλετε σίγουρα να φύγετε από τη σελίδα;</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Αποστολή</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Ανεβάστε
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Το βίνεο δημοσιεύτηκε.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Το βίντεο έχει σκληρό περιεχόμενο ή μόνο για ενήλικες. Σίγουρα θέλετε να το δείτε;</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Σκληρό περιεχόμενο ή για ενήλικες</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Επόμενο</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Ακύρωση</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Μειώστε το ποσοστό αναπαραγωγής (απαιτεί εστίαση του προγράμματος αναπαραγωγής))</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Περιήγηση στο βίντεο καρέ ανά καρέ (απαιτεί εστίαση του προγράμματος αναπαραγωγής)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Σας αρέσει το βίντεο</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Ban this user</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>User</target>
<source>Username or email address</source>
<target>Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Forgot your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target>Create an account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target>Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target>Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target>Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Unfollow</target>
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target>Update the user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Video channel
<source>Ownership change request sent.</source>
<target>Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>My channels</target>
<target>Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target>Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Your password has been successfully reset!</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="final">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="final">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="final"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="final">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="final">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="final">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="final"> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<source>Federation</source>
<target state="final">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="final">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="final">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="final">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="final">Ban this user</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="final"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="final"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="final">User</target>
<source>Username or email address</source>
<target state="final">Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="final"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="final">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="final">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="final"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="final">Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="final">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="final">Forgot your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="final">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="final"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="final">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="final">Email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="final">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target state="final">Create an account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="final">My videos</target>
<target state="final">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="final">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="final">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="final">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="final">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="final">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="final">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="final">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="final">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="final">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="final">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="final">Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="final">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="final">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="final">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="final">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="final">Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="final">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="final">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="final">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="final">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target state="final">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="final"> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="final">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="final">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="final">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="final">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="final">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="final">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="final">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="final">My Channels</target>
<source>Your message has been sent.</source>
<target state="final">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="final">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="final">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="final">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="final">VIDEOS</target>
<target state="final">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="final">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="final"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="final">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="final">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="final">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="final">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="final">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="final">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="final">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="final">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="final">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="final">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="final">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="final">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="final">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="final">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="final">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="final">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="final">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="final">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="final">Do you really want to unfollow <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="final">Unfollow</target>
<source>You are not following <x id="PH"/> anymore.</source>
<target state="final">You are not following <x id="PH"/> anymore.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="final">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="final">Standard logs</target>
<source>Update user password</source>
<target state="final">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="final">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="final">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="final">User <x id="PH"/> updated.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="final">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="final">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="final">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="final">Videos will be deleted, comments will be tombstoned.</target>
<target state="final">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="final">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="final">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="final">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="final">You cannot ban root.</target>
<source>Video channel <x id="PH"/> created.</source>
<target state="final">Video channel <x id="PH"/> created.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="final">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="final">Video channel <x id="PH"/> updated.</target>
<source>Banner deleted.</source><target state="final">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="final">Please type the display name of the video channel (<x id="PH"/>) to confirm</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="final">Video channel <x id="PH"/> deleted.</target>
<source>Ownership change request sent.</source>
<target state="final">Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="final">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="final">My channels</target>
<target state="final">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="final">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target state="final">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="final">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="final">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="final">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="final">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="final">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="final">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="final">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="final">Trending</target>
<source>Incorrect username or password.</source>
<target state="final">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="final">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="final">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="final">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="final">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="final">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="final">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="final">Your password has been successfully reset!</target>
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="final">Too many attempts, please try again after <x id="PH"/> minutes.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="final">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="final">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="final">Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</target>
<source>Your video was uploaded to your account and is private.</source>
<target state="final">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="final">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="final">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="final">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="final">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="final">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="final">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="final">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="final">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="final">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="final">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="final">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="final">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="final">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="final">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="final">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="final">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="final">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="final">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="final">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="final">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="final">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="final">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="final">Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Historio de mia spektado</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">filmo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Datumlimo por filmoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Senlima <x id="START_TAG_NG_CONTAINER"/>(po <x id="INTERPOLATION"/> tage) <x id="CLOSE_TAG_NG_CONTAINER"/></target>
<source>Federation</source>
<target>Federaĵo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106">
<source>followers</source>
<target>abonantoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Forbari ĉi tiun uzanton</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Ĉi tiu nodo permesas registriĝojn. Tamen zorge tralegu <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>la uzokondiĉojn<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>uzokondiĉojn<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> antaŭ ol vi kreos konton. Eble vi ankaŭ povus trovi nodon, kiu precize konvenos viajn bezonojn, per: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Ĉi tiu nodo nun ne permesas registriĝon de uzantoj. Vi povas malkovri pliajn detalojn per <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>la uzokondiĉoj<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> aŭ trovi nodon, kiu ebligas registradon de kontoj kaj alŝutadon de filmoj. Trovu la vian inter pluraj nodoj per: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Uzanto</target>
<source>Username or email address</source>
<target>Salutnomo aŭ retpoŝtadreso</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Pasvorto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Klaku ĉi tien por restarigi vian pasvorton</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Mi forgesis pasvorton</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Salutinte vian konton, vi povas publikigi enhavon</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Saluti</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Aŭ saluti per</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Forgesita pasvorto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target>
Ni pardonpetas; vi ne povas rehavi vian pasvorton, ĉar la administranto de via nodo ne agordis la retpoŝtan sistemon de PeerTube.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Enigu vian retpoŝtadreson kaj ni sendos al vi retleteron por restarigi vian pasvorton.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Retpoŝtadreso</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Retpoŝtadreso</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Restarigi</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>Krei konton</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">FILMOJ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="translated">Mi estas tekruĉo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Tio estas eraro.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">La vidaŭdaĵo estas tro granda por la servilo. Bonvolu kontakti vian administranton, se vi volas pligrandigi la datumlimon.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Pardonu, la alŝuta funkcio estas malŝaltita por via konto. Se vi volas aldoni filmojn, administranto devas malŝlosi vian datumlimon.</target>
<target>Identigilo</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Nomo de abonanto</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Stato</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Gastiganto</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Ripetaĵo permesita <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<source>Unfollow</source>
<target state="translated">Malaboni</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Malfermi nodon en nova langeto</target>
<source>No host found matching current filters.</source>
<target state="translated">Neniu gastiganto troviĝis per la nunaj filtriloj.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Via nodo neniun abonas.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Montrante <x id="INTERPOLATION"/> ĝis <x id="INTERPOLATION_1"/> el <x id="INTERPOLATION_2"/> gastigantoj</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Aboni domajnojn</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Aboni nodojn</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Salutnomo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">ekz. ushio_shiromija</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rolo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Transkodado estas ŝaltita. Ĉi tiu datumlimo konsideras <x id="START_TAG_STRONG"/>originalan<x id="CLOSE_TAG_STRONG"/> grandecon de la filmo. <x id="LINE_BREAK"/> Plej grande ĉi tiu uzanto povus alŝuti ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Aŭtentikiga kromprogramo</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Neniu (loka aŭtentikigo)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="translated">Komentita filmo</target>
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Ŝajnas, ke vi ne uzas servilon kun HTTPS. Via retservilo bezonas aktivan protokolon TLS por aboni servilojn.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Silentigi domajnojn</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Ĉu vi certe volas forigi <x id="PH"/>? Tio forigos ĉiujn filmojn alŝutitajn de <x id="PH_1"/> al ĉi tiu kanalo, kaj vi ne povos krei alian kanalon kun la sama nomo (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="translated">Miaj kanaloj</target>
<source>Your message has been sent.</source>
<target>Via mesaĝo sendiĝis.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Vi jam sendis ĉi tiun respondilon freŝdate</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> rektaj abonantoj de konto
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Raporti ĉi tiun konton</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target>Salutnomo kopiiĝis</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 abonanto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> abonantoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Nodoj, kiujn vi abonas</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Nodoj, kiuj vin abonas</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Nur sono</target>
<source>Auto (via ffmpeg)</source>
<target>Memage (per ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Domajno estas postulata.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Enigitaj domajnoj estas nevalidaj.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Enigitaj domajnoj enhavas duoblaĵojn.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Senlima</target>
<x id="PH"/> forigita el abonantoj de nodo
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> ne validas
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Abonpetoj senditaj!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Ĉu vi certe volas malaboni <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Malaboni</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Vi ne plu abonas <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>ŝaltita</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Eraro</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Normaj protokoloj</target>
<target>Ĝisdatigi pasvorton de uzanto</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Listo de abonatoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Listo de abonantoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Uzanto <x id="PH"/> ĝisdatigita.</target>
<target state="translated">Federaĵo</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Abonataj nodoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Abonantaj nodoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Filmoj foriĝos, komentoj tombiĝos.</target>
<target>Agordi retpoŝtadreson konfirmita</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Vi ne povas forbari ĉefuzanton.</target>
<source>Video channel <x id="PH"/> created.</source>
<target>Filma kanalo <x id="PH"/> kreita.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Ĉi tiu nomo jam ekzistas ĉe ĉi tiu nodo.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Filma kanalo <x id="PH"/> ĝisdatigita.</target>
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Bonvolu entajpi la prezentan nomon de la filma kanalo (<x id="PH"/>) por konfirmi</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Filma kanalo <x id="PH"/> forigita.</target>
<source>Ownership change request sent.</source>
<target>Peto de poseda ŝanĝo sendiĝis.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Aboni la konton</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Iri al miaj abonoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Iri al miaj filmoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Iri al miaj enportoj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Iri al miaj kanaloj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Ne povas ekhavi salutilojn de OAuth Client: <x id="PH"/>. Certigu, ke PeerTube estas ĝuste agordita (en la dosierujo config/), precipe la sekcio «webserver».</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Vi devas rekonektiĝi.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Fulmoklavoj:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Malĝusta salutnomo aŭ pasvorto.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Via konto estas blokita.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">ajna lingvo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">kaŝi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">malklarigi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">montri</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Nekonata</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Via pasvorto estas sukcese restarigita!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Tro multaj petoj; bonvolu reprovi post <x id="PH"/> minutoj.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Tro multaj provoj; bonvolu reprovi poste.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Servila eraro. Bonvolu reprovi poste.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Abonanta ĉiujn nunajn kanalojn de <x id="PH"/>. Vi sciiĝos pri ĉiuj ĝiaj novaj filmoj.</target>
<source>Your video was uploaded to your account and is private.</source>
<target>Via filmo alŝutiĝis al via konto kaj estas privata.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Sed rilataj informoj (etikedoj, priskribo…) perdiĝos; ĉu vi certe volas folasi ĉi tiun paĝon?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Via filmo ankoraŭ ne alŝutiĝis; ĉu vi certe volas forlasi ĉi tiun paĝon?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Alŝuti</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Alŝuti
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Filmo publikigita.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Ĉi tiu filmo ne estas disponebla per ĉi tiu nodo. Ĉu vi volas alidirektiĝi al la devena nodo: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Alidirektiĝo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Tiu ĉi video povas esti konsterna aŭ maltaŭga por neplenaĝuloj. Ĉu vi certe volas spekti ĝin?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Konsterna aŭ maltaŭga por neplenaĝaj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Sekve</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Nuligi</target>
<source>Autoplay is suspended</source>
<target state="translated">Memludado estas haltigita</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Eniĝi/eliĝi tutekranan reĝimon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Ludi/Paŭzgi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Silentigi/Malsilentigi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Salti al elcenta progreso en la filmo: 0 estas 0% kaj 9 estas 90% (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Plilaŭtigi (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Mallaŭtigi (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Pluigi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Malpluigi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Plirapidigi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Malrapidigi la filmon (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navigi tra la filmo po filmeroj (bezonas fokusitan ludilon)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Ŝati la filmon</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Mi historial de visionados</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Crear</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">El siguiente enlace contiene un token privado y no debe compartirse con nadie.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Su cuota de video se excede con este video (tamaño del video:<x id="PH" equiv-text="videoSizeBytes"/>, usado: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Su cuota diaria de video se excede con este video (tamaño del video:<x id="PH" equiv-text="videoSizeBytes"/>, usado: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">subtítulos</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Cupo de vídeos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Illimitado <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> por día) <x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Federación</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>cancelar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Expulsar este usuario</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Esta instancia permite el registro. Sin embargo, tenga cuidado de comprobar las <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Condiciones<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Condiciones<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>antes de crear una cuenta. También puede buscar otra instancia que coincida con sus necesidades exactas en: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Actualmente, esta instancia no permite el registro de usuarios, puede marcar la <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>para obtener más detalles o busque una instancia que le brinde la posibilidad de registrarse para obtener una cuenta y cargar sus videos allí. Encuentre el suyo entre varias instancias en:<x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Usuario</target>
<source>Username or email address</source>
<target>Nombre de usuario o correo electrónico</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Contraseña</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Haga clic aquí para restablecer la contraseña</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Olvidé mi contraseña</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Iniciar sesión en una cuenta le permite publicar contenido</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Iniciar sesión</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">O inicia sesión con</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Contraseña olvidada</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Lo sentimos, no es posible recuperar la contraseña porque el administrador de la instancia no ha configurado el sistema de correo electrónico de PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Ingrese su dirección de correo electrónico y le enviaremos un enlace para restablecer su contraseña.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Correo electrónico </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Correo electrónico </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Reiniciar</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">en esta instancia</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Crear una cuenta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Mis videos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VÍDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Importar simultaneidad de trabajos</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Soy una tetera</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Eso es un error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">El medio es demasiado grande para el servidor. Comuníquese con su administrador si desea aumentar el tamaño del límite.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">BÚSQUEDA GLOBAL</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Subir en espera</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Lo sentimos, la función de carga está deshabilitada para su cuenta. Si desea agregar videos, un administrador debe desbloquear su cuota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Control de seguidor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Estado</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundancia permitida <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Dejar de seguir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Abrir instancia en una pestaña nueva</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">No se ha encontrado ningún host que coincida con los filtros actuales.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Tu instancia no sigue a nadie.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Mostrando <x id="INTERPOLATION"/> a <x id="INTERPOLATION_1"/> de <x id="INTERPOLATION_2"/> hosts</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Seguir dominios</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Seguir instancias</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Acción</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nombre de usuario</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">ejemplo: jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rol</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">La transcodificación está habilitada. La cuota de video solo tiene en cuenta el peso <x id="START_TAG_STRONG"/>original <x id="CLOSE_TAG_STRONG"/> del vídeo. <x id="LINE_BREAK"/> Como máximo, este usuario podría subir ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Complemento de autenticación</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Ninguna autenticación local</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Parece que no estás en un servidor HTTPS. Su servidor web necesita tener TLS activado para seguir otros servidores.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Dominios silenciados</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">CANALES</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Esta cuenta no tiene canales.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">¿Realmente quieres eliminar <x id="PH" equiv-text="videoChannel.displayName"/>? Se eliminarán<x id="PH_1" equiv-text="videoChannel.videosCount"/>videos subidos en este canal ¡y no podrás crear otro canal con el mismo nombre (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>Su mensaje ha sido enviado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Ya envió este formulario recientemente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Videos de cuenta</target>
<target state="translated">
<x id="PH"/> seguidores de cuenta directa
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Informar sbre esta cuenta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VÍDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Nombre de usuario copiado</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 suscriptor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> suscriptores</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancias que sigues</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancias que te siguen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Solo audio</target>
<source>Auto (via ffmpeg)</source>
<target>Auto (vía ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Se requiere dominio.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Los dominios ingresados no son válidos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Los dominios ingresados contienen duplicados.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Ilimitado</target>
<x id="PH"/> eliminado de seguidores de instancia
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> no es válido
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>¡Petición(es) de seguimiento enviada(s)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>¿De verdad quieres dejar de seguir a <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Dejar de seguir</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Ya no estás siguiendo a <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>habilitada</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Registros estándar</target>
<target state="translated">Actualizar contraseña de usuario</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Lista de seguidores</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Lista de seguidores</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Usuario <x id="PH"/> actualizado.</target>
<target state="translated">Federación</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancias que sigues</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancias siguiéndote</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Los videos serán eliminados, los comentarios serán destruidos.</target>
<target>Establecer la dirección de correo electrónico como Verificada</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Canal de vídeo <x id="PH"/> creado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>El nombre ya existe en esta instancia.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Canal de vídeo <x id="PH"/> actualizado.</target>
<target state="translated">Banner eliminado.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Escriba el nombre para mostrar del canal de video ( <x id="PH"/>) para confirmar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Canal de vídeo <x id="PH"/> eliminado.</target>
<source>Ownership change request sent.</source>
<target>Solicitud de cambio de titularidad enviada.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Suscribirse a la cuenta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">LISTAS DE REPRODUCCIÓN</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Ir a mis suscripciones</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Ir a mis vídeos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Ir a mis importaciones</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Ir a mis canales</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">No se pueden recuperar las credenciales del cliente OAuth: <x id="PH" equiv-text="error.text"/>. Asegúrese de haber configurado correctamente PeerTube (config / directorio), en particular la sección "servidor web".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Tienes que reconectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Atajos de teclado:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>El nombre de usuario o la contraseña son incorrectos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Tu cuenta está bloqueada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">cualquier idioma</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">esconder</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">difuminar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">monitor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Desconocido</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>¡Tu contraseña ha sido restablecida con éxito!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Demasiados intentos, por favor inténtalo de nuevo pasados <x id="PH"/> minutos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Demasiados intentos, por favor inténtelo más tarde.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Error del servidor. Por favor, inténtalo más tarde.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Suscrito a todos los canales actuales de <x id="PH"/>. Serás notificado de todos sus nuevos videos.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Tu vídeo ha sido subida a tu cuenta y es privado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Pero los datos asociados (etiquetas, descripción...) se perderán, ¿seguro que quieres abandonar esta página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Tu vídeo aún no se ha subido, ¿seguro que quieres abandonar esta página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Subir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Cargue
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vídeo publicado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="translated">¡Usted tiene cambios no guardados! Si te vas, tus cambios se perderán.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Este video no está disponible en esta instancia. ¿Quieres ser redirigido a la instancia de origen: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Redirección</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Este vídeo contiene material para adultos o explícito. ¿Seguro que lo quieres ver?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Contenido para adultos o explícito</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Hasta la siguiente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Cancelar</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">La reproducción automática está suspendida</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Entrar/salir de pantalla completa (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Reproducir / Pausar el video (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Silenciar / activar el video (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Salte a un porcentaje del video: 0 es 0% y 9 es 90% (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Aumenta el volumen (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Disminuye el volumen (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Buscar el video hacia adelante (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Busque el video hacia atrás (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Aumentar la velocidad de reproducción (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Disminuir la velocidad de reproducción (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navegue en el video cuadro por cuadro (requiere foco en el reproductor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Colocar Me gusta a este vídeo</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Nire ikustaldien erregistroa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">bideoa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Bideo-kuota</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<source>Federation</source>
<target state="translated">Federazioa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">jarraitzaile</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Debekatu erabiltzaile hau</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Erabiltzailea</target>
<source>Username or email address</source>
<target>Erabiltzaile-izena edo eposta helbidea</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Pasahitza</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Egin klik hemen zure pasahitza berrezartzeko</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Pasahitza ahaztu dut</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Kontu batekin sartzeak edukia argitaratzea ahalbidetuko dizu</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Hasi saioa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Edo hasi saioa honekin</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Pasahitza ahaztu duzu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Sentitzen dugu, ezin duzu zure pasahitza berreskuratu, instantziaren administratzaileak ez baitzuen PeerTubeko posta elektronikoko sistema konfiguratu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Sartu zure eposta helbidea eta zure pasahitza berrezartzeko esteka bat bidaliko dizugu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Eposta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Eposta helbidea</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Berrezarri</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>Sortu kontu bat</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">BIDEOAK</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Multimedia-fitxategia handiegia da zerbitzarirako. Kontaktatu administratzailea tamaina-muga handitu nahi baduzu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Igotzeko-funtzioa desgaituta dago zure konturako. Bideoak gehitu nahi badituzu, administratzaile batek zure kuota desblokeatu behar du.</target>
<target>ID-a</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Egoera</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Ostalaria </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Zabaldu instantzia fitxa berri batean</target>
<source>No host found matching current filters.</source>
<target state="translated">Ez da aurkitu iragazkiekin bat datorren ostalaririk.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Zure instantziak ez du besterik jarraitzen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Jarraitu domeinuak</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Erabiltzaile izena</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rola</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Badirudi ez zaudela HTTPS zerbitzari batean. Zure web zerbitzariak TLS aktibatuta eduki behar du zerbitzariak jarraitu ahal izateko.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Mututu domeinuak</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="translated">Nire kanalak</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target>Automatikoa (ffmpeg bidez)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Mugagabea</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> baliogabea da
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Jarraitzeko eskaria(k) bidalita!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Ziur
<x id="PH"/> jarraitzeari utzi nahi diozula?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Utzi jarraitzeari</target>
<target>Ez duzu jada
<x id="PH"/> jarraitzen.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>gaituta</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Errorea</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Jo eposta egiaztatutzat</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Ezin duzu root debekatu</target>
<x id="PH"/> bideo kanala sortuta.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Izen hau hartuta dago instantzia honetan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>
<source>Ownership change request sent.</source>
<target>Jabetza aldatzeko eskaria bidalita.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Harpidetu kontura</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Joan nire harpidetzetara</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Joan nire bideoetara</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Joan nire inportazioetara</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Joan nire kanaletara</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Berriro konektatu behar duzu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Teklatu laster-bideak:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Erabiltzaile-izen edo pasahitz okerra.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Zure pasahitza ongi berrezarri da!</target>
<target>Saiakera gehiegi, saiatu berriro geroago,
<x id="PH"/> minutu igarotakoan.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Saiakera gehiegi, saiatu berriro geroago.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Zerbitzariaren errorea, Saiatu berriro geroago.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>Zure bideoa zure kontura igo da eta pribatua da.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Baina dagozkion datuak (etiketak, deskripzioa...) galduko dira, ziur orri hau utzi nahi duzula?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Zur bideoa ez da igo oraindik, ziur orri hau utzi nahi duzula?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Bideoa argitaratuta.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Bideo honek helduentzako edo hunkigarria den edukia du. Ziur ikusi nahi duzula?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Helduentzako edo hunkigarria den edukia</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Gehitu bideoa gogokoetara</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565" datatype="html">
<source>Create</source>
<target state="new">Create</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">پیوند زیر دارای یک رمز خصوصی است و نباید با کسی به اشتراک گذاشته شود.</target>
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">با این ویدیو از سهمیه ویدیوی شما بیشتر می شود (اندازه ویدیو: <x id="PH" equiv-text="videoSizeBytes"/>، استفاده شده: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>، سهم : <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">سهمیه ویدئویی روزانه شما با این ویدیو (اندازه ویدیو: <x id="PH" equiv-text="videoSizeBytes"/>استفاده شده: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>، سهم: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">زیرنویس</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="new">Video quota</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>کاربر</target>
<source>Username or email address</source>
<target>نام کاربری یا آدرس رایانامه</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>گذرواژه</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>ورود</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>گذرواژهتان را فراموش کردهاید</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>رایانامه</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>آدرس رایانامه</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<target>ساخت حساب</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>میزبان</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target state="new">Username</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>نقش</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="new">This account does not have channels.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<target state="new">Video channel
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>ویدئو انتشاریافت</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="new">You have unsaved changes! If you leave, your changes will be lost.</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Sulje tämä käyttäjä</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Käyttäjä</target>
<source>Username or email address</source>
<target>Käyttäjänimi tai sähköpostiosoite</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Kirjaudu sisään</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Unohda salasanasi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Sähköpostiosoite</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target>Luo tili</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Seuraajan käsittelijä</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Tila</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Isäntä</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target>Rooli</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target>Viestisi on lähetetty.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Lähetit jo tämän lomakkeen vasta.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target>Käyttäjänimi kopioitu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target>Automaattinen (ffmpeg avulla)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Rajaton</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895">
<source>
<x id="PH"/> is not valid
<x id="PH"/> ei ole sallittu
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Seurantapyynnöt lähetetty!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Lopeta seuranta</target>
<x id="PH"/> enään.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>käytössä</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target>Päivitä tilin salasana</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Aseta sähköpostiosoite vahvistetuksi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Et voi estää root-käyttäjää.</target>
<x id="PH"/> luotiin.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Tämä nimi on jo olemassa tässä instanssissa.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Videokanava
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target>Omistajuudenvaihtopyyntö lähetetty.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Minun kanavat</target>
<target>Tilaa käyttäjä</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target>Mene tilauksiini</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Mene videoihini</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Mene tuonteihini</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Mene kanaviini</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Sinun pitää yhdistää udelleen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Pikanäppäimet:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Virheellinen käyttäjänimi tai salasana.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Liian monta yritystä, yritä myöhemmin uudelleen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Palvelinvirhe. Yritä myöhemmin uudelleen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Videota ei ole vielä ladattu, haluatko varmasti poistua sivulta?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video julkaistu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Tämä video sisältää aikuisille tarkoitettua sisältöä. Haluatko varmasti jatkaa?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Aikuisille tarkoitettu sisältö</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Tykkää videosta</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Mon historique de visionnage</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Créer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">vidéo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Le lien suivant contient un jeton privé et ne doit être partagé avec personne.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Votre quota est dépassé avec cette vidéo (taille de la vidéo : <x id="PH" equiv-text="videoSizeBytes"/>, utilisé : <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota : <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Votre quota journalier est dépassé avec cette vidéo (taille de la vidéo : <x id="PH" equiv-text="videoSizeBytes"/>, utilisé : <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota : <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">sous-titres</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Quota des vidéos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Illimité <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> par jour)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target>Fédération</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Annuler</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Bannir cet·te utilisateur·rice</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Cette instance permet l'enregistrement. Toutefois, il faut veiller à vérifier les <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>conditions d'utilisation<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>conditions d'utilisation<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> avant de créer un compte. Vous pouvez également rechercher une autre instance correspondant exactement à vos besoins sur : <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Actuellement, cette instance ne permet pas l'enregistrement des utilisateurs, vous pouvez vérifier les <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>conditions d'utilisation<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> pour plus de détails ou trouvez une instance qui vous donne la possibilité de créer un compte et d'y télécharger vos vidéos. Trouvez la vôtre parmi plusieurs instances à l'adresse suivante : <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Utilisateur·rice</target>
<source>Username or email address</source>
<target>Identifiant ou adresse de courriel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Mot de passe</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Cliquez ici pour réinitialiser votre mot de passe</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">J'ai oublié mon mot de passe</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">La connexion à un compte vous permet de publier du contenu</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Se connecter</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Ou connectez vous</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Oubli de votre mot de passe</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target>Nous sommes désolés, vous ne pouvez pas réinitialiser votre mot de passe car l'administrateur·rice de votre instance n'a pas configuré le système de courrier électronique de PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Saisissez votre adresse électronique et nous vous enverrons un lien pour réinitialiser votre mot de passe.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Courriel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Adresse de courriel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Réinitialiser</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">sur cette instance</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Créer un compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Mes vidéos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDÉOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Importer des travaux en même temps</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Je suis une théière</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">C'est une erreur.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Ce média est trop gros pour le serveur. Merci de contacter votre administrateur pour augmenter cette limite.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">RECHERCHE GLOBALE</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Téléversement en attente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Désolé, la fonction de téléchargement est désactivée pour votre compte. Si vous souhaitez ajouter des vidéos, un administrateur doit débloquer votre quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Identifiant d'abonné·e</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Statut</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Hôte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redondance autorisée <x id="START_TAG_P-SORTICON"/><x id="CLOSE_TAG_P-SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Arrêter de suivre</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Ouvrir l'instance dans une nouvelle fenêtre</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Impossible de trouver un hôte correspondant aux critères actuels.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Votre instance n'en suit aucune autre.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Affiche <x id="INTERPOLATION"/> à <x id="INTERPOLATION_1"/> sur <x id="INTERPOLATION_2"/>hôtes</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Suivre des domaines</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Suivre les instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Identifiant</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">exemple : joel_dove</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rôle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Le transcodage est activé. Le quota de vidéos ne prend en compte que la taille du fichier <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/>.<x id="LINE_BREAK"/> L'utilisateur peut au plus téléverser ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Plugin d'authentification</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Aucune (authentification locale)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Il semblerait que votre serveur n'utilise par le protocole HTTPS. Vous devez activer TLS sur votre serveur pour pouvoir en suivre d'autres.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Masquer des domaines</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">CHAÎNES</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Ce compte n'a pas de chaîne vidéo.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Voulez-vous vraiment supprimer <x id="PH" equiv-text="videoChannel.displayName"/> ? Cela supprimera <x id="PH_1" equiv-text="videoChannel.videosCount"/> les vidéos mises en ligne sur cette chaîne, et vous ne pourrez pas créer une autre chaine avec le même nom (<x id="PH_2" equiv-text="videoChannel.name"/>) !</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>Votre message a été envoyé.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Vous avez déjà rempli ce formulaire récemment</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Vidéos du compte</target>
<target state="translated">
<x id="PH"/> comptes abonnés
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Signaler ce compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDÉOS</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>Nom d'utilisateur·rice copié</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 abonné</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> abonnés</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Les instances que vous suivez</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Les instances qui vous suivent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Audio seulement</target>
<source>Auto (via ffmpeg)</source>
<target>Auto (avec ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Un domaine est requis.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Les domaines renseignés sont invalides.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Les domaines renseignés contiennes des doublons.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Illimité</target>
<x id="PH"/> supprimé des abonné·e·s de votre instance
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> n'est pas valide
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Requête·s envoyée·s !</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Voulez-vous vraiment vous désabonner de <x id="PH"/> ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Arrêter le suivi</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Vous n'êtes plus abonné·e à <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>activé</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Erreur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Journaux standards</target>
<target>Mettre à jour le mot de passe utilisateur·rice</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Instances suivies</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Instances qui nous suivent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Utilisateur·rice <x id="PH"/> mis·e à jour.</target>
<target state="translated">Fédération</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instances que vous suivez</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instances qui vous suivent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Les vidéos seront supprimées, les commentaires seront marqués supprimés.</target>
<target>Définir l'adresse de courriel comme vérifiée</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Chaîne vidéo <x id="PH"/> créée.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Ce nom existe déjà sur cette instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Chaîne vidéo <x id="PH"/> mise à jour.</target>
<target state="translated">Bannière supprimée.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Merci de saisir le nom de la chaîne vidéo ( <x id="PH"/>) pour confirmer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Chaîne vidéo <x id="PH"/> supprimée.</target>
<source>Ownership change request sent.</source>
<target>Requête de changement de propriété envoyée.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>S'abonner à ce compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">LISTES DE LECTURE</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Aller voir mes abonnements</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Aller voir mes vidéos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Aller voir mes imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Aller voir mes chaînes</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Impossible de récupérer les identifiants du Client OAuth : <x id="PH" equiv-text="error.text"/>. Assurez-vous d'avoir correctement configuré PeerTube (dossier config/), en particulier la section "serveur web".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Vous devez vous reconnecter.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Raccourcis clavier :</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Nom d'utilisateur ou mot de passe incorrects.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Votre compte est bloqué.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">toute langue</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">cacher</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">flouter</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">afficher</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Inconnu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Votre mot de passe a été réinitialisé avec succès !</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Trop de tentatives, merci de réessayer dans <x id="PH"/> minutes.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Trop d'essais. Merci de réessayer plus tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Le serveur rencontre une erreur. Merci de réessayer plus tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Abonné·e à toutes les chaînes actuelles de <x id="PH"/>. Vous serez avertis·es de toutes leurs nouvelles vidéos.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Votre vidéo a été téléversée sur votre compte et elle est privée.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Les données associées (étiquettes, description, etc.) seront par contre perdues ; êtes-vous sûr·e de vouloir quitter cette page ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Votre vidéo n'est pas encore téléversé ; êtes-vous sûr·e de vouloir quitter cette page ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Mise en ligne</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Téléverser
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vidéo publiée.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Vous n'avez pas sauvegardé vos modifications ! Si vous quittez la page, vous les perdrez.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Cette vidéo n'est pas disponible sur cette instance ? Voulez-vous être redirigé sur l'instance d'origine : <a href="<x id="PH"/>"><x id="PH_1"/></a> ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Cette vidéo contient du contenu sensible. Êtes-vous sûr·e de vouloir la regarder ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Contenu explicite ou sensible</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Suivant</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Annuler</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">La lecture automatique est suspendue</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Entrer/sortir du mode plein écran (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Lecture/Pause de la vidéo (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Désactiver/Activer le son de la vidéo (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Sauter à un pourcentage de la vidéo : 0 est 0 % et 9 est 90 % (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Augmenter le volume (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Diminuer le volume (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Avancer la vidéo (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Reculer la vidéo (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Augmenter la vitesse de lecture (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Diminuer la vitesse de lecture (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Naviguer dans la vidéo image par image (nécessite le focus sur le lecteur)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>J’aime cette vidéo</target>
<trans-unit id="187187500641108332" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Eachdraidh dhe na choimhead mi air</target>
<trans-unit id="5674286808255988565" datatype="html">
<source>Create</source>
<target state="translated">Cruthaich</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Tha tòcan prìobhaideach am broinn a’ cheangail a leanas agus cha bu chòir dhut a cho-roinneadh le duine sam bith.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Chaidh thu thar cuota nam videothan agad leis a’ video seo (meud a’ video: <x id="PH" equiv-text="videoSizeBytes"/>, ’ga chleachdadh: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, cuota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Bheir a’ video seo thar cuota làitheil nam videothan agad thu (meud a’ video: <x id="PH" equiv-text="videoSizeBytes"/>, ’ga chleachdadh: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, cuota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">fo-thiotalan</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="translated">Cuota de videothan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="translated">Gun chuingeachadh <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> gach latha)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Co-nasgadh</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Sguir dheth</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="translated">Toirmisg an cleachdaiche seo</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Faodaidh tu clàradh air an ionstans seo.Gidheadh, dèan cinnteach gun leugh thu na <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Teirmichean<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Teirmichean<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> mus cruthaich thu cunntas. ’S urrainn dhut cuideachd ionstans eile a lorg a fhreagras ris na feumalachdan agad-sa: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Cha cheadaich an t-ionstans seo gun clàraich cleachdaichean ùra aig an àm seo, ’s urrainn dhut sùil a thoirt air na <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Teirmichean<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> airson barrachd fiosrachaidh no ionstans a lorg a bheir comas clàraidh cunntais dhut agus na videothan agad a luchdadh suas an-siud. Lorg an t-ionstans agad fhèin am measg càich: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="translated">Cleachdaiche</target>
<source>Username or email address</source>
<target state="translated">Ainm-cleachdaiche no seòladh puist-d</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
<target state="translated">Facal-faire</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Briog an-seo airson am facal-faire agad ath-shuidheachadh</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Dìochuimhnich mi am facal-faire agam</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Ma nì thu clàradh a-steach air cunntas, ’s urrainn dhut susbaint fhoillseachadh</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="translated">Clàraich a-steach</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">No clàraich a-steach le</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="translated">Na dhìochuimhnich thu am facal-faire agad?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Tha sinn duilich ach chan urrainn dhut am facal-faire agad aiseag air sgàth ’s nach do rèitich rianaire an ionstans seo siostam puist-d PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Cuir a-steach an seòladh puist-d agad agus cuiridh sinn ceangal thugad gus am facal-faire agad ath-shuidheachadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target state="translated">Post-d</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="translated">Seòladh puist-d</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Ath-shuidhich</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">air an ionstans seo</target>
<trans-unit id="2308975396733519902" datatype="html">
<source>Create an account</source>
<target state="translated">Cruthaich cunntas</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Na videothan agam</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOTHAN</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Co-ruith nan obraichean ion-phortaidh</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">’S e poit-tì a th’ annam</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Seo mearachd.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Tha am meadhan ro mhòr airson an fhrithealaiche. Cuir fios gun rianaire agad ma tha thu airson crìoch a’ mheud a mheudachadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">LORG UILE-CHOITCHEANN</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Tha an luchdadh suas ’ga cumail air ais</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Tha sinn duilich ach chaidh gleus an luchdaidh suas a chur à comas dhan chunntas agad. Ma tha thu airson videothan a chur ris, feumaidh rianaire an glas a thoirt far a’ chuota agad.</target>
<target state="translated">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Làimhsichear neach-leantainn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="translated">Staid</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="translated">Òstair</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Tha anabarrachd ceadaichte <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Na lean tuilleadh</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Fosgail an t-ionstans ann an taba ùr</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Cha deach òstair a lorg a fhreagras ris na criathragan làithreach.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Chan eil an t-ionstans agad a’ leantainn air dad sam bith.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">A’ sealltainn <x id="INTERPOLATION"/> gu <x id="INTERPOLATION_1"/> à <x id="INTERPOLATION_2"/> òstair(ean)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Lean air àrainnean</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Lean air ionstansan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Gnìomh</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target state="translated">Ainm-cleachdaiche</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">m.e.: mairi_mhor</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="translated">Dreuchd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Tha an tar-chòdachadh an comas. Cha dèid ach meud <x id="START_TAG_STRONG"/>tùsail<x id="CLOSE_TAG_STRONG"/> nam videothan a chunntadh mu choinneamh a’ chuota. <x id="LINE_BREAK"/> B’ urrainn dhan chleachdaiche seo mu <x id="INTERPOLATION"/> a luchdadh suas air a char as motha. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Plugan dearbh-aithneachaidh</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Chan eil gin (dearbh-aithneachadh ionadail)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Tha coltas nach eil thu air frithealaiche HTTPS. Feumaidh am frithealaiche agad TLS a chur an comas mus lean e air frithealaichean eile.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Mùch àrainnean</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">SEANAILEAN</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Chan eil seanail aig a’ chunntas seo.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">A bheil thu cinnteach gu bheil thu airson <x id="PH" equiv-text="videoChannel.displayName"/> a sguabadh às?Sguabaidh seo às <x id="PH_1" equiv-text="videoChannel.videosCount"/> video(than) a chaidh a luchdadh suas dhan t-seanail seo ’s chan urrainn dhut seanail eile air a bheil an t-aon ainm (<x id="PH_2" equiv-text="videoChannel.name"/>) a chruthachadh!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target state="translated">Chaidh an teachdaireachd agad a chur.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">Chuir thu am foirm seo a-null o chionn greis mu thràth</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Videothan a’ chunntais</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> luchd-leantainn dìreach a’ chunntais </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Dèan gearan mun chunntas seo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOTHAN</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Chaidh lethbhreac a dhèanamh dhen ainm-chleachdaiche</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">Rinn 1 fo-sgrìobhadh air</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated">Rinn <x id="PH"/> fo-sgrìobhadh air</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Na h-ionstansan air a leanas tu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Na h-ionstansan a tha a’ leantainn ort</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Fuaim a-mhàin</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Fèin-obrachail (slighe ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Tha àrainn-lìn riatanach.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Chaidh àrainn mhì-dhligheach a chur a-steach.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Tha dùblachadh am measg nan àrainnean a chaidh a chur a-steach.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">Gun chrìoch</target>
<source><x id="PH"/> removed from instance followers </source>
<target state="translated">Chaidh <x id="PH"/> a thoirt air falbh ach nach lean e air an ionstans tuilleadh </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="translated">Chan eil <x id="PH"/> dligheach </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="translated">Chaidh iarrtas(an) leantainn a chur!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">A bheil thu cinnteach gu bheil thu airson sgur de leantainn air <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Na lean tuilleadh</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Chan eil thu a’ leantainn air <x id="PH"/> tuilleadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="translated">an comas</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">Mearachd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Logaichean àbhaisteach</target>
<target state="translated">Ùraich facal-faire a’ chleachdaiche</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Liosta dhen fheadhainn air a leanas tu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Liosta dhen fheadhainn a leanas ort</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Chaidh an cleachdaiche <x id="PH"/> ùrachadh.</target>
<target state="translated">Co-nasgadh</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Na h-ionstansan air a leanas tu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Na h-ionstansan a tha a’ leantainn ort</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Thèid na videothan a sguabadh às agus comharra sguabaidh às a chur ris na beachdan.</target>
<target state="translated">Suidhich gun deach am post-d a dhearbhadh</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">Chaidh seanail video <x id="PH"/> a chruthachadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Tha an t-ainm seo ann air an ionstans seo mu thràth.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">Chaidh seanail video <x id="PH"/> ùrachadh.</target>
<target state="translated">Chaidh a’ bhratach a sguabadh às.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Sgrìobh ainm-taisbeanaidh na seanail video (<x id="PH"/>) gus a dhearbhadh</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">Chaidh seanail video <x id="PH"/> a sguabadh às.</target>
<source>Ownership change request sent.</source>
<target state="translated">Chaidh iarrtas a chur air atharrachadh an t-seilbh.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">Fo-sgrìobh air a’ chunntas</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">LIOSTAICHEAN-CLUICH</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Tadhail air na fo-sgrìobhaidhean agam</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Tadhail air na videothan agam</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Tadhail air na h-ion-phortaidhean agam</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Tadhail air na seanailean agam</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Cha b’ urrainn dhuinn an teisteas cliant OAuth fhaighinn: <x id="PH" equiv-text="error.text"/>. Dèan cinnteach gun do rèitich thu PeerTube mar bu chòir (sa phasgan config/) ’s gu sònraichte an earrann "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">Feumaidh tu ceangal ris a-rithist.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Ath-ghoiridean a’ mheur-chlàir:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">Chan eil an t-ainm-cleachdaiche no chan eil am facal-faire mar bu chòir.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Chaidh an cunntas agad a bhacadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">cànan sam bith</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">falaich</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">sgleò</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">taisbean</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Chan eil fhios</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">Chaidh am facal-faire agad ath-shuidheachadh!</target>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">Cus oidhirpean, feuch ris a-rithist an ceann <x id="PH"/> mionaid(ean).</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="translated">Cus oidhirpean, feuch ris a-rithist an ceann greis.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="translated">Mearachd an fhrithealaiche. Feuch ris a-rithist an ceann greis.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Fhuair thu fo-sgrìobhadh air na seanailean làithreach uile aig <x id="PH"/>. Gheibh thu brathan-naidheachd mu na videothan ùra aca uile.</target>
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">Chaidh a’ video agad a luchdadh suas dhan chunntas agad ’s tha e prìobhaideach.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="translated">Ach thèid dàta sam bith nach deach a shàbhaladh (tagaichean, tuairisgeulan…) air chall, a bheil thu cinnteach gu bheil thu airson an duilleag seo fhàgail?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="translated">Cha deach a’ video agad a luchdadh suas fhathast, a bheil thu cinnteach gu bheil thu airson an duilleag seo fhàgail?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Luchdaich suas</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Luchdaich suas <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">Chaidh a’ video fhoillseachadh.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="translated">Tha atharraichean gun sàbhaladh agad! Ma dh’fhalbhas tu, thèid na h-atharraichean agad air chall.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Chan eil a’ video seo ri fhaighinn air an ionstans seo. A bheil thu airson ’s gun dèid d’ ath-stiùireadh dhan ionstans thùsail: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Ath-stiùireadh</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="translated">Tha susbaint sa video seo a tha iomchaidh do dh’inbhich a-mhàin. A bheil thu cinnteach gu bheil thu airson coimhead air?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="translated">Susbaint do dh’inbhich</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Ri thighinn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Sguir dheth</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Chaidh a’ chluiche fhèin-obrachail a chur à rèim</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">A-steach/a-mach às a’ mhodh làn-sgrìn (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Cluich a’ video/Cuir ’na stad e (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Mùch/Dì-mhùch a’ video (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Thoir leum gu ceudad dhen video: Bheir 0 gu 0% thu agus 9 gu 90% (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Meudaich àirde na fuaime (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Lùghdaich àirde na fuaime (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Sir air adhart sa video (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Sir air ais sa video (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Dèan a’ chluich nas luaithe (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Dèan a’ chluich nas maille (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Seòl tron video frèam air fhrèam (bidh an cluicheadair feumach air an fhòcas)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">Comharraich gur toigh leat a’ video</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Historial de visualizacións</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Crear</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">A seguinte ligazón contén un token privado e non deberías compartilo con ninguén.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Este vídeo fai que superes a túa cota de vídeo (tamaño do vídeo: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, cota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Con este vídeo superas a túa cota diaria de vídeo (tamaño do vídeo: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, cota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">subtítulos</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Cota de vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Sen límite <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> diario)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Federación</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Cancelar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Vetar esta usuaria</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Esta instancia ten o rexistro aberto. Non obstante, pon tino en comprobar <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Termos<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Os Termos<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> antes de crear unha conta. Podes atopar outra instancia máis acorde ás túas necesidades en: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Actualmente esta instancia non permite abrir unha conta, podes ler os <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Termos<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> para saber máis ou atopar outra instancia co rexistro aberto e poder subir alí os teus vídeos. Atopa a túa entre varias opcións en: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Usuaria</target>
<source>Username or email address</source>
<target>Nome de usuaria ou enderezo de correo</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Contrasinal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Preme aquí e restablece o contrasinal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Esquecín o contrasinal</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Se estás conectada poderás publicar o teu contido</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Conectar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Ou conéctate con</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Esqueceu o contrasinal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Lamentámolo, non podes recuperar o contrasinal porque a administración da instancia non configurou o sistema de email de PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Escribe o teu email e enviarémosche unha ligazón para restablecer o contrasinal.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Correo electrónico</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Enderezo de correo electrónico</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Restablecer</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">nesta instancia</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Crear unha conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Vídeos</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VÍDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Concurrencia de tarefas de importación</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Son unha teteira</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">É un erro.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">O multimedia é demasiado grande para o servidor. Contacta coa administración se desexas que aumenten o límite.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">BUSCA GLOBAL</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Subida agardando</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Lamentámolo, a túa conta non permite subir contidos. Se queres engadir vídeos, unha administradora debe aumentar a túa cota.</target>
<target state="translated">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Xestión da seguidora</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="translated">Estado</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="translated">Servidor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundancia permitida <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Deixar de seguir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Abrir instancia en nova lapela</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Non se atoparon servidores co criterio do filtro.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">A túa instancia non segue a ninguén.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Mostrando <x id="INTERPOLATION"/> a <x id="INTERPOLATION_1"/> de <x id="INTERPOLATION_2"/> servidores</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Seguir dominios</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Seguir instancias</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Acción</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nome de usuaria</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">ex. ugio_ben</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="translated">Rol</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Recodificación activada. A cota de vídeo só ten en conta o tamaño <x id="START_TAG_STRONG"/>orixinal<x id="CLOSE_TAG_STRONG"/> do vídeo. <x id="LINE_BREAK"/> Como moito, esta usuaria podería subir ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Complemento Auth</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Ningún (autenticación local)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Semella que non estás nun servidor HTTPS. O teu servidor web precisa ter TLS activado para poder seguir servidores.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Acalar dominios</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">CANLES</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Esta conta non ten canles.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Desexas eliminar <x id="PH" equiv-text="videoChannel.displayName"/>? Así eliminarás <x id="PH_1" equiv-text="videoChannel.videosCount"/> vídeos subidos a esta canle, e non poderás volver a crear outra canle co mesmo nome (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target state="translated">A túa mensaxe foi enviada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">Xa enviaras este formulario recentemente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Vídeos da conta</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> seguidoras directas da conta </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Denunciar esta conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VÍDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Nome de usuaria copiado</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 subscritora</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> subscritoras</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancias que segues</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancias que te seguen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Só audio</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Auto (vía ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Requírese un dominio.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">O dominio escrito non é válido.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Hai duplicados nos dominios escritos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">Sen límite</target>
<source><x id="PH"/> removed from instance followers </source>
<target state="translated"><x id="PH"/> eliminada das seguidoras da instancia </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="translated"><x id="PH"/> non é válido </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="translated">Solicitude(s) de seguimento enviada(s)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Desexas deixar de seguir a <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Deixar de seguir</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Xa non segues <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="translated">activado</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">Erro</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Rexistros estándar</target>
<target state="translated">Actualizar contrasinal da usuaria</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Lista de seguimentos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Lista de seguidoras</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Usuaria <x id="PH"/> actualizada.</target>
<target state="translated">Federación</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancias que segues</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancias que te seguen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Os vídeos serán eliminados, os comentarios serán soterrados.</target>
<target state="translated">Establecer email como Verificado</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">Creada a canle de vídeo <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Este nome xa existe nesta instancia.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">Actualizada a canle de vídeo <x id="PH"/>.</target>
<target state="translated">Cabeceira eliminada.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Escribe o nome a mostrar para a canle de vídeo (<x id="PH"/>) para confirmar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">Eliminada a canle de vídeo <x id="PH"/>.</target>
<source>Ownership change request sent.</source>
<target state="translated">Enviouse a solicitude de cambio de propiedade.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">Subscribirse á conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">LISTAXES</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Ir ás miñas subscricións</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Ir ós meus vídeos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Ir ás importacións</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Ir ás miñas canles</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Non se poden obter as credenciais OAuth Client: <x id="PH" equiv-text="error.text"/>. Asegúrate de ter configurado correctamente PeerTube (config/ directory), en particular a sección "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">Tes que reconectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Atallos de teclado:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">Usuaria ou contrasinal incorrectos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">A túa conta está bloqueada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">tódolos idiomas</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">agochar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">esborranchar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">mostrar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Descoñecido</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">Restableceuse correctamente o contrasinal!</target>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">Demasiados intentos, inténtao outra vez tras <x id="PH"/> minutos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="translated">Demasiados intentos, inténtao máis tarde.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="translated">Erro do servidor. Inténtao máis tarde.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Subscrita a tódalas canles de <x id="PH"/>. Recibirás notificación de tódolos seus vídeos.</target>
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">O vídeo subeuse á túa conta e é privado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="translated">Pero os datos asociados (etiquetas, descrición...) perderanse, queres saír igualmente desta páxina?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="translated">O vídeo aínda non se subiu, desexas realmente saír desta páxina?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Subir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Subir <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">Vídeo publicado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="translated">Tes cambios sen gardar! Se saes perderás os cambios.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Este vídeo non está dispoñible na túa instancia. Queres ser redirixida á instancia orixinal: <a href="<x id="PH"/>"><x id="PH_1"/>/a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Redirección</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="translated">Este vídeo contén contido explicito ou adulto. Tes certeza de querer velo?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="translated">Contido explícito ou adulto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">A seguir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Cancelar</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Reprodución automática suspendida</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Entrar/Saír da pantalla completa (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Reproducir/Pausar o vídeo (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Acalar/Restablecer o vídeo (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Saltar a unha porcentaxe do vídeo: 0 é 0% e 9 é 90% (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Aumentar volume (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Diminuír volume (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Saltar adiante no vídeo (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Saltar atrás no vídeo (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Aumentar taxa de reprodución (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Diminuir taxa de reprodución (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navegar fotograma a fotograma (require foco no reprodutor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">Gústame o vídeo</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Saját megtekintési előzmények</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">videó</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">feliratok</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Videokvóta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Korlátlan <x id="START_TAG_NG_CONTAINER"/>(napi <x id="INTERPOLATION"/>)<x id="CLOSE_TAG_NG-CONTAINER"/></target>
<source>Federation</source>
<target state="translated">Föderáció</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">követő</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Felhasználó kitiltása</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Felhasználó</target>
<source>Username or email address</source>
<target>Felhasználónév vagy e-mail-cím</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Jelszó</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Kattintson ide a jelszava visszaállításához</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Bejelentkezés</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Vagy jelentkezzen be ezzel:</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Elfelejtett jelszó</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Sajnáljuk, de nem tudja helyreállítani a jelszavát, mert a példány rendszergazdája nem állította be a PeerTube levelezőrendszerét.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-mail-cím</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">ezen a példányon</target>
<target>Fiók létrehozása</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">VIDEÓK</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">A média túl nagy ehhez a kiszolgálóhoz. Lépjen kapcsolatba a rendszergazdával, ha növelni szeretné a méretkorlátot.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Sajnáljuk, a feltöltési funkció tiltott a fiókjában. Ha videókat akar hozzáadni, akkor egy rendszergazdának fel kell oldania a kvótája zárolását.</target>
<target>Azonosító</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Követőkezelő</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Állapot</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="translated">Gép</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundancia megengedett <x id="START_TAG_P-SORTICON"/><x id="CLOSE_TAG_P-SORTICON"/></target>
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Példány megnyitása új lapon</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Nem található a jelenlegi szűrőkre illeszkedő gép.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Az Ön példánya nem követ senkit sem.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated"><x id="INTERPOLATION"/> – <x id="INTERPOLATION_1"/> / <x id="INTERPOLATION_2"/> gép megjelenítése</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Tartományok követése</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Felhasználónév</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Szerep</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Az átkódolás engedélyezve van. A videokvóta csak az <x id="START_TAG_STRONG"/>eredeti <x id="CLOSE_TAG_STRONG"/> videó méretét veszi figyelembe. <x id="LINE_BREAK"/> Ez a felhasználó legfeljebb ~ <x id="INTERPOLATION"/>-ot tölthet fel. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Úgy tűnik, hogy nem HTTPS kiszolgálón van. A TLS-nek bekapcsolva kell lennie a webkiszolgálóján, hogy kiszolgálókat követhessen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Tartományok némítása</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Ennek a fióknak nincsenek csatornái.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Biztos, hogy törli a(z) <x id="PH" equiv-text="videoChannel.displayName"/> csatornát? Ez törli a csatornára feltöltött <x id="PH_1" equiv-text="videoChannel.videosCount"/> videót, és nem hozhat létre még egy csatornát ugyanezzel a névvel (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target>Az üzenete el lett küldve.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Már nemrég elküldte ezt az űrlapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Fiók videói</target>
<target state="translated">
<x id="PH"/> közvetlen fiókkövető
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Fiók jelentése</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEÓK</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Felhasználónév lemásolva</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 feliratkozó</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> feliratkozó</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Példányok, amiket követ</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Példányok, amik követik</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Csak hang</target>
<source>Auto (via ffmpeg)</source>
<target>Automatikus (ffmpeg által)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Tartomány szükséges.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">A megadott tartományok érvénytelenek.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">A megadott tartományok kettőzéseket tartalmaznak.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">Korlátlan</target>
<x id="PH"/> eltávolítva a példány követőiből
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="translated">
<x id="PH"/> nem érvényes
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="translated">Követési kérések elküldve!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Biztos, hogy megszünteti a(z) <x id="PH"/> követését?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Követés megszüntetése</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Többé már nem követi a(z) <x id="PH"/> gépet.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="translated">engedélyezve</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">Hiba</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Szabványos naplók</target>
<target state="translated">Felhasználó jelszavának frissítése</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Követési lista</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Követők listája</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated"><x id="PH"/> felhasználó frissítve.</target>
<target state="translated">Föderáció</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Követett példányok</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Követő példányok</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">A videók törölve lesznek, a hozzászólások el lesznek temetve.</target>
<target state="translated">E-mail beállítása ellenőrzöttre</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="translated">Nem tilthatja ki a rendszergazdát.</target>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">A(z) <x id="PH"/> videócsatorna létrehozva.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Ez a név már létezik ebben a példányban.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">A(z) <x id="PH"/> videocsatorna frissítve.</target>
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Írja be a videócsatorna megjelenített nevét ( <x id="PH"/>) a megerősítéshez</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">A(z) <x id="PH"/> videócsatorna törölve.</target>
<source>Ownership change request sent.</source>
<target state="translated">Tulajdonjog-változtatási kérelem elküldve.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">Feliratkozás a fiókra</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Ugrás a feliratkozásaimhoz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Ugrás a videóimhoz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Ugrás az importálásaimhoz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Ugrás a csatornáimhoz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Az OAuth kliens hitelesítő adatai nem kérhetők le: <x id="PH" equiv-text="error.text"/>. Győződjön meg róla, hogy helyesen állította be a PeerTube-ot (konfiguráció / könyvtár), különösképpen a „webserver” szakaszban.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">Újra kell csatlakoznia.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Gyorsbillentyűk:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">Helytelen felhasználónév vagy jelszó.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">A fiókja le van tiltva.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">bármely nyelv</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">elrejtés</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">homályosítás</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">megjelenítés</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Ismeretlen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">A jelszava sikeresen vissza lett állítva!</target>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">Túl sok próbálkozás. Próbálja meg újra <x id="PH"/> perc múlva.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="translated">Túl sok próbálkozás. Próbálja meg újra később.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="translated">Kiszolgálóhiba. Próbálja újra később.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Feliratkozva <x id="PH"/> összes jelenlegi csatornájára. Értesítést fog kapni az összes új videójukról.</target>
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">A videó fel lett töltve a fiókjába, és személyes.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="translated">De a kapcsolódó adatok (címkék, leírás, …) el fognak veszni. Biztosan el szeretné hagyni ezt az oldalt?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="translated">A videó még nincs feltöltve. Biztosan el szeretné hagyni ezt az oldalt?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Feltöltés</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">
<x id="PH"/> feltöltése
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">Videó közzétéve.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Ez a videó nem érhető el ezen a példányon. Szeretné, hogy átirányítsuk a forráspéldányhoz: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Átirányítás</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="translated">Ez a videó felnőtt vagy korhatáros tartalmat tartalmaz. Biztosan meg szeretné nézni?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="translated">Felnőtt vagy korhatáros tartalom</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Legközelebb</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Mégse</target>
<source>Autoplay is suspended</source>
<target state="translated">Az automatikus lejátszás fel van függesztve</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Teljes képernyőre váltás vagy normál méret (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">A videó lejátszása vagy szüneteltetése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">A videó némítása vagy a némítás visszavonása (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Kihagyás a videó százalékáig: a 0 jelentése 0%, a 9 jelentése 90% (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">A hangerő növelése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">A hangerő csökkentése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">A videó előretekerése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">A videó visszatekerése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Lejátszási sebesség növelése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Lejátszási sebesség csökkentése (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navigálás a videóban képkockánként (lejátszófókuszt igényel)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">A videó kedvelése</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">La mia cronologia di visualizzazione</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Quota video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Illimitato <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> al giorno)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<source>Federation</source>
<target state="translated">Federazione</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">follower</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Espelli questo utente</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Questa istanza consente la registrazione. Tuttavia, fai attenzione a controllare i <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Termini<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Termini<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>prima di creare un account. Puoi anche cercare un'altra istanza per soddisfare le tue esigenze esatte su: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/it/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Attualmente questa istanza non consente la registrazione dell'utente, puoi controllare i <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Termini<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> per maggiori dettagli o per trovare un'istanza che ti dà la possibilità di registrare un'account e caricare i tuoi video lì. Trova il tuo tra più istanze su:<x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/it/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Utente</target>
<source>Username or email address</source>
<target>Nome utente o indirizzo email</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Clicca qui per resettare la tua password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Ho dimenticato la mia password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">L'accesso a un account ti consente di pubblicare contenuti</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Accedi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">O accedi con</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Password dimenticata</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Ci scusiamo, non c'è modo di recuperare la tua password perchè l'amministratore dell'istanza non ha configurato il sistema di email di PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Inserisci il tuo indirizzo email e ti invieremo un link per reimpostare la tua password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Indirizzo email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Reimposta</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>Crea un account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">VIDEO</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="translated">Sono una teiera</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Questo è un errore.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Il video è troppo grande per il server. Contatta il tuo amministratore se desideri aumentare la dimensione del limite.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Spiacente, la funzionalità di upload è disabilitata per il tuo account. Se vuoi aggiungere video, un amministratore deve sbloccare la tua quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Gestione seguaci</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Stato</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Ridondanza consentita <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<source>Unfollow</source>
<target state="translated">Smetti di seguire</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Apri l'istanza in una nuova scheda</target>
<source>No host found matching current filters.</source>
<target state="translated">Nessun host trovato corrispondente ai filtri correnti.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">La tua istanza non sta seguendo nessuno.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Mostra <x id="INTERPOLATION"/> a <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Segui domini</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Segui istanze</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nome utente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">esempio: maria_rossi</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Ruolo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">La transcodifica è abilitata. La quota video prende in considerazione solo <x id="START_TAG_STRONG"/>dimensione<x id="CLOSE_TAG_STRONG"/> originale del video. <x id="LINE_BREAK"/> L'utente dovrebbe poter caricare ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="translated">Video commentati</target>
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Sembra che tu non sia su un server HTTPS. Il tuo server web deve avere TLS attivato per poter seguire i server.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Silenzia domini</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Vuoi davvero eliminare <x id="PH" equiv-text="videoChannel.displayName"/>? Verranno eliminati <x id="PH_1" equiv-text="videoChannel.videosCount"/> i video caricati in questo canale e non potrai creare un altro canale con lo stesso nome <x id="PH_2" equiv-text="videoChannel.name"/></target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="translated">I miei Canali</target>
<source>Your message has been sent.</source>
<target>Messaggio inviato.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Questo modulo è stato usato di recente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> follower diretti dell'account </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Segnala questo account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="translated">Nome utente copiato</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 sottoscrittore</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> sottoscrittori</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Istanze che segui</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Istanze che ti seguono</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Solo audio</target>
<source>Auto (via ffmpeg)</source>
<target>Auto (tramite ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Il Dominio è richiesto.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">I domini inseriti non sono validi.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">I domini inseriti contengono duplicati.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Illimitato/ti</target>
<source><x id="PH"/> removed from instance followers </source>
<target state="translated"><x id="PH"/> rimosso dai follower dell'istanza </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> non è valida
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Richiesta/e per seguire (follow) spedita/e!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Vuoi veramente smettere di seguire <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Smetti di seguire (unfollow)</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Non stai seguendo piú <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>attivato</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Errore</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Logs standard</target>
<target>Aggiorna password dell' utente</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Elenco seguente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Elenco followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Utente <x id="PH"/> aggiornato.</target>
<target state="translated">Federazione</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Istanze che segui</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Istanze che ti seguono</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">I video verranno eliminati, i commenti verranno rimossi definitivamente.</target>
<target>Imposta email come verificata</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Non puoi espellere root.</target>
<source>Video channel <x id="PH"/> created.</source>
<target>Il canale video <x id="PH"/> è stato creato.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Questo nome esiste già nell'istanza.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Il canale video <x id="PH"/> è stato aggiornato.</target>
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Digita il nome visualizzato del canale video ( <x id="PH"/>) per confermare</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Il canale video <x id="PH"/> è stato cancellato.</target>
<source>Ownership change request sent.</source>
<target>Richiesta di cambio proprietario spedita.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Iscriversi all'account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Vai alle mie iscrizioni</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Vai ai miei video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Vai alle mie importazioni</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Vai ai miei canali</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Impossibile recuperare le credenziali del Client OAuth: <x id="PH" equiv-text="error.text"/>. Assicurati di aver configurato correttamente PeerTube (config/ directory), in particolare la sezione "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Devi riconnetterti.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Scorciatoie per la tastiera:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Nome utente o password non corretti.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Il tuo account è bloccato.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">qualsiasi lingua</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">nascondi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">sfocatura</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">schermo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Sconosciuto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>La tua password è stata reimpostata con successo!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Troppi tentativi, si potrà provare di nuovo dopo <x id="PH"/> minuti.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Troppi tentativi, riprovare più tardi.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Errore del server. Riprovare più tardi.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Iscrizione a tutti i canali correnti di <x id="PH"/>. Riceverai una notifica di tutti i loro nuovi video.</target>
<source>Your video was uploaded to your account and is private.</source>
<target>Il video è stato caricato sul proprio account ed è privato.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>I dati associati (tag, descrizione, ...) saranno persi. Chiudere questa pagina ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Il tuo video non è ancora caricato. Sei sicuro di volere chiudere questa pagina ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Carica</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Carica<x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video pubblicato.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Questo video non è disponibile su questa istanza. Vuoi essere reindirizzato sull'istanza di origine: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Redirezione</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Questo video contiene del contenuto sensibile. Sei sicuro di volerlo guardare?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Contenuto per adulti o esplicito</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Avanti il prossimo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Annulla</target>
<source>Autoplay is suspended</source>
<target state="translated">Autoplay sospeso</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Entra / esci dallo schermo intero (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Riproduci / Metti in pausa il video (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Disattiva / riattiva il video (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Passa a una percentuale del video: 0 è 0% e 9 è 90% (richiede il focus del player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Aumenta il volume (richiede il focus del player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Abbassa il volume (richiede il focus del player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Cerca il video in avanti (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Cerca il video all'indietro (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Aumenta la velocità di riproduzione (richiede focus del player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Diminuisci la velocità di riproduzione (richiede la messa a fuoco del player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navigare nel video fotogramma per fotogramma (richiede focus player)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Mi piace</target>
<trans-unit id="187187500641108332" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>作成</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">字幕</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>動画容量の制限</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>無制限 <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/>/ 日) <x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">連合</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>キャンセル</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>このユーザーをBANする</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>ユーザー</target>
<source>Username or email address</source>
<target>ユーザー名かメールアドレス</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>パスワード</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">クリックしてパスワードをリセットします</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">パスワードを忘れました</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">あなたのアカウントでログインする事で、コンテンツを公開することができます</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>ログイン</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>パスワードをお忘れですか</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">申し訳ありません。インスタンス管理者がPeerTubeのメールシステムの設定をしていないため、パスワードを復元することができません。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">メールアドレスを入力すれば、パスワードをリセットするためのリンクが送信されます。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>メールアドレス</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>メールアドレス</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">リセット</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>アカウントを作成する</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">自分の動画</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">動画</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">I am a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="needs-translation">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">グローバル検索</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>状態</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>ホスト</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">新しいタブでインスタンスを開く</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">あなたのインスタンスはまだ誰もフォローしていません。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">ドメインをフォロー</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">インスタンスをフォローする</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>ユーザー名</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">e.g.jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>権限</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">ミュートしたドメイン</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">チャンネル</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">このアカウントはチャンネルを持ってません。</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>メッセージを送信しました。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>このフォームに最近送信しています</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">このアカウントの動画</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">アカウントを通報する</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">ユーザー名をコピーしました</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">チャンネル登録者1人</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated">チャンネル登録者数 <x id="PH"/> 人</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">音声のみ</target>
<source>Auto (via ffmpeg)</source>
<target>自動 (FFmpeg 経由)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">ドメインが必要です。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">入力されたドメインは無効です。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>無制限</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> は無効です。
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>フォローリクエストを送信しました!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>本当に <x id="PH"/> のフォローを解除しますか?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>フォロー解除</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>あなたはもう <x id="PH"/> をフォローしていません。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>有効</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>エラー</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">標準のログ</target>
<target>ユーザーパスワードを更新する</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">フォローリスト</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">フォロワーリスト</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">User <x id="PH"/> updated.</target>
<target state="translated">他インスタンスとの連合</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">フォローしているインスタンス</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">フォローされているインスタンス</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">動画が削除され、コメントも削除されます。</target>
<target>メールを確認済みとして設定</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>動画チャンネル <x id="PH"/> を作成しました。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>この名前は、このインスタンス上に既に存在します。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>動画チャンネル: <x id="PH"/> を更新しました。</target>
<target state="translated">バナーが削除されました。</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>動画チャンネル ( <x id="PH"/>) の表示名を入力してください</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>動画チャンネル <x id="PH"/> を削除しました。</target>
<source>Ownership change request sent.</source>
<target>所有権の変更リクエストが送信されました。</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>アカウントを購読する</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">プレイリスト</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>自分の登録チャンネルへ移動</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>動画一覧</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>インポートした動画一覧</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>マイチャンネルに移動する</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>再接続する必要があります。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>キーボードショートカット:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>ユーザー名またはパスワードが違います。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">あなたのアカウントはブロックされてます。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">表示しない</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">ぼかす</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">表示する</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>パスワードは正常にリセットされました!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>試行回数が多すぎます。 <x id="PH"/> 分後にもう一度お試しください。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>試行回数が多すぎます。しばらくしてからもう一度お試しください。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>サーバーエラーです。 後でもう一度やり直してください。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>動画はこのアカウントに非公開でアップロードされています。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>関連するデータ (タグ、説明など) は失われます。このページから移動してもよろしいですか?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>動画はまだアップロードされていません。このページから移動してもよろしいですか?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">アップロード</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">アップロード <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>動画が投稿されました。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>保存していない変更があります。 ページを移動すると、変更した内容は失われます。</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">リダイレクト</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>この動画には成人向けまたは過激なコンテンツが含まれています。本当に再生しますか?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>成人向けまたは過激なコンテンツ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">キャンセル</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">自動再生は停止中です</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">再生速度を早くする (アクティブのプレーヤーが必要)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">再生速度を遅くする (アクティブのプレーヤーが必要)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>高く評価</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>lo pilno</target>
<source>Username or email address</source>
<target state="new">Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>co'a cmisau</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>.i mi nalmo'i le mi lerpoijaspu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>lo ve samymri</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target>zbasu lo pilno</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>.i mo'u mrilu lo jersi pe'a ve cpedu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>co'u jersi pe'a</target>
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target state="new">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> .ly. noi vidvi te tivni
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>.i le cmene xa'o zasti ci'e le mupli</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>.i mo'u galfi la'o ly.
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>.i mo'u vimcu la'o ly.
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>lo mi te tivni</target>
<target>jersi pe'a le pilno</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target>klama lo se jersi pe'a be mi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>klama lo mi vidvi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>klama lo se nerbei be mi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>klama lo mi te tivni</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>.i snada lo nu mo'u galfi le do japyvla</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>.i lo se vidvi mo'u co'a gubni</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>nu zanru lo se vidvi</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Azray-inu n tmeẓriwt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3099741642167775297" datatype="html">
<source>Download</source>
<target>Sider</target>
<source>video</source>
<target>tavidyut</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Aseɣwen-a deg-s ajuṭun sli, ur ilaq ara ad yettwabḍu ula d yiwen.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">iduzwilen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="6325096236207614377" datatype="html">
<source>Reason...</source>
<target state="translated">Taɣẓint...</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="translated">Amur n tvidyut</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="translated">War tilas <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/>i wass)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<source>Federation</source>
<target state="translated">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">Ineḍfaren</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Tummant-a tsareg ajerred. Γas akken, ɣur-k·m senqed <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Tiwtilin<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Tiwtilin<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> send timerna n umiḍan. Tzemreḍ daɣen ad tnadiḍ tummant-nniḍen i wakken ad yemṣada swaswa wayen i tuḥwaǧeḍ deg: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Akka tura tummant-a ur tsirig ara ajerred n yiseqdacen, ilaq ad tesneqdeḍ <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Tiwtilin<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> i wugar n telqayt neɣ i tifin n tummant ara ak·am-imudden tazmert n ujerred i umiḍan, syen ad d-tsalayeḍ tividyutin din. Af-d ayla-k·m gar waṭas n tummanin yemgaraden deg: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target>Aseqdac</target>
<source>Username or email address</source>
<target>Isem n useqdac neɣ tansa imayl</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
<target>Awal uffir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Si da akken ad twenzeḍ awal uffir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Ttuɣ awal-iw uffir</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Anekcum ɣer umiḍan ad ak·akem-yeǧǧ ad tsuffɣeḍ agbur</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target>Tuqqna</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="translated">Tettuḍ awal-ik uffir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Suref-aɣ, ur tezmireḍ ara ad d-terreḍ awal-inek·inem uffir acku anedbal-ik·im n tummant ur isefrek ara anagraw n yimayl n PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Sekem tansa-inek·inem n yimayl syen nekkni ad ak·am-n-aznen aseɣwen i wakken ad twennzeḍ awal-ik·im uffir.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target>Imayl</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target>Tansa email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Wennez</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">deg tummant-a</target>
<target>Rnu amiḍan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="8936704404804793618" datatype="html">
<source>Videos</source>
<source>VIDEOS</source>
<target state="translated">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Kter imahilen yemqaraben</target>
<source>I'm a teapot</source>
<target state="translated">Nekk d t·amsatay·t</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Tagi d tuccḍa.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">midyat ɣezzif aṭas i uqeddac-a. Ma ulac aɣilif nermes anedbal-ik·im ma yella tebɣiḍ ad ternuḍ deg teɣzi n talast.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="2468689683507870964" datatype="html">
<source>In this instance's network</source>
<target state="translated">Deg uzeṭṭa n tummant-a</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Nesḥassef, tamahilt n usali tensa i umiḍan-ik·im. Ma yella tebɣiḍ ad ternuḍ tividyutin, anedbal yezmer ad yekkes asekker afmiḍi-inek·inem.</target>
<target state="translated">Tavidyut/Awennit/Amiḍan</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Abagan n uneḍfar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="3301856295120048857" datatype="html">
<source>State <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Addad n <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<target state="translated">Ɛwed ajuṭun amynut</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-applications/my-account-applications.component.html</context><context context-type="linenumber">35</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target>Asneftaɣ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Tuɣalin tettusireg <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<source>Unfollow</source>
<target state="translated">Ḥbes aḍfar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Ldi tummant deg yiccer amaynut</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Ulac inebgi yettwafen yemṣada d yimsizedgen imiranen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Tummant-ik·im ulac win i teṭṭafar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Sken <x id="INTERPOLATION"/> i <x id="INTERPOLATION_1"/> n <x id="INTERPOLATION_2"/> yinebgawen</target>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Akka i d-yettban mačči ɣef uqeddac HTTPS i telliḍ. Aqeddac-ik·im web yesra ad yettwarmed TLS i uḍfar n yiqeddacen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Ḍfer taɣulin</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Ḍfer tummanin</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Tigawt</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target>Nom d'utilisateur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">am. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target>Tamlilt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Anigtengel yermed. Ableɣ n tvidyut yettaṭṭaf akan teɣzi <x id="START_TAG_STRONG"/>taneẓlit<x id="CLOSE_TAG_STRONG"/> n tvidyut. <x id="LINE_BREAK"/> Deg tuget, aseqdac-a yezmer ad d-isali ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Izegrar n usesteb</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Ulac (alɣu adigan)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Tebɣiḍ s tidet ad tekkseḍ <x id="PH" equiv-text="videoChannel.displayName"/>? Ad yekkes <x id="PH_1" equiv-text="videoChannel.videosCount"/> tividyutin i d-yettwasulin deg ubadu-a, syen ur tettizmired ara ad ternuḍ abadu-nniḍen s yisem-nni kan (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">IBUDA</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Amiḍan-a ulac ɣur-s ibuda n tvidyut.</target>
<source>Your message has been sent.</source>
<target state="translated">Izen-ik·im yettwazen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">Tuzneḍ yakan tiferkit-a</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Tividyutin n umiḍan</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> ineḍfaren n umiḍan usriden </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Azen aneqqis ɣef umiḍan-a</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Yettwanɣel yisem n useqdac</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 umulteɣ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> yimultaɣ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Tummanin i teṭṭafareḍ</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Tummanin i ak·akem-yeṭṭafaren</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="3008420115644088420" datatype="html">
<source>Configuration</source>
<target>Tawila</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Awurman (s ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Taɣult tettusra.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Tiɣula yettwaskecmen d tarimeɣta.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Tiɣula yettwaskecmen yella deg-sent uεiwed.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="translated"><x id="PH"/> d arameɣtu </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target>War talast</target>
<source><x id="PH"/> removed from instance followers </source>
<target state="translated"><x id="PH"/> yettwakkes sɣur ineḍfaren n tummant </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="translated">Asuter n uḍfar yettwazen!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Tebɣiḍ s tidet ad tḥebseḍ aḍfar n <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Ur ṭṭafarara</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Ur teṭṭafareḍ <x id="PH"/> yiwen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target>irmed</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target>Tuccḍa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Standard logs</target>
<target state="translated">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Tabdart n uḍfar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Tabdart n yineḍfaren</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Aseqdac <x id="PH"/> yettwaleqqem.</target>
<target state="translated">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Tummanin teṭṭafareḍ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Tummanin i ak·akem-yeṭṭafaren</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Tividyutin ad ttwakksent, iwenniten ad ttwasfesxen.</target>
<target state="translated">Sbadu imayl am wakken yettusenqed</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="translated">Ur tezmired ara ad tgedleḍ aseqdac aẓar.</target>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">Abadu n tvidyut <x id="PH"/> yettwarna.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Isem-a yella yakan ɣef tummant-a.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">Abadu n tvidyut <x id="PH"/> yettwaleqqem.</target>
<target state="translated">Aɣrrac yettwakkes.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Ttxil-k·m aru isem yettwaskanen n ubadu n tvidyut ( <x id="PH"/>) i usentem</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">Abadu n tvidyut <x id="PH"/> yettwakkes.</target>
<source>Ownership change request sent.</source>
<target state="translated">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Multeɣ ɣer umiḍan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">TIBDARIN N TΓURI</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Ddu ɣer yimultaɣ-inu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Ddu ɣer tvidyutin-inu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Ddu ɣer waktaren-inu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Ddu ɣer yibuda-inu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">D awezɣi ad d-nerr inekcam n umsaɣ OAuth: <x id="PH" equiv-text="error.text"/>. Ḍmen belli tsewleḍ PeerTube akken iwata (akaram n uswel/), aṭas tigezmi n "aqeddac web".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">Tesriḍ ad teqqneḍ.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Inegzumen n unaswi:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target>Isem n useqdac neɣ awal n uɛeddi d urameɣtu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Amiḍan-ik·im yettusewḥel.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target>ffer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">sken</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target>D arussin</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">yal tutlayt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">Aṭas n tikkal i tεerḍeḍ, ttxil-k·m εreḍ tikkelt-nniḍen seld <x id="PH"/> tesdatin.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="translated">Aṭas n yineεruḍen, ttxil-k·m εreḍ tikkelt-nniḍen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="translated">Tuccḍa deg uqeddac. Ttxil-k·m εreḍ tikkelt-nniḍen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Multeɣ ɣer meṛṛa ibuda imiranen n <x id="PH"/>. Ad d-teṭṭfeḍ ilɣa ɣef meṛṛa tividyutin timaynutin.</target>
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">Tavidyut-ik·im tettwasuli ɣer umiḍan-ik·im yerna d tusligt.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="translated">Maca ad tesruḥeḍ isefka yemcudden (tibzimin, aglam...), d tidet tebɣiḍ ad teffɣeḍ seg usebter-a?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="translated">Tavidyut-a mazal ur d-tettwasuli ara, d tidet tebɣiḍ ad teffɣeḍ seg usebter-a?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Sali</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Sali-d <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">Tavidyut yettwasuffɣen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Tavidyut-a ulac-itt deg tummant. Tebɣiḍ ad tettuwellheḍ ɣer tummant taneẓlit: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Allus n uwelleh</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="translated">Tavidyut-a deg-s agbur ai yimeqqranen neɣ agbur amḥulfu. D tidet tebɣiḍ ad t-twaliḍ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="translated">Agbur i yimeqqranen neq agbur amḥulfu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Uḍfir</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Sefsex</target>
<source>Autoplay is suspended</source>
<target state="translated">Taɣuri tawurmant tettwaseḥbes</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Kcem/ffeɣ askar n ugdil aččuran (yesra afukus ɣef yimeɣri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Taɣuri/Aḥbas n tvidyutPause(yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Sgugem/kkes asgugem tavidyut (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Ɛeddi ɣer ufmiḍi n tvidyut: 0 d 0% akked 9 d 90% (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Snerni ablaɣ (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Senqes ableɣ (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Seddu tavidyut ɣer sdat (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Err tavidyut ɣer deffir (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Snerni arured n tɣuri (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Senqes arured n tɣuri (yesra afukus n tɣuri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Inig deg tvidyut tugna s tugna (yesra afukus ɣef yimeɣri)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">Teεǧeb-iyi tavidyut</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">동영상</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>영상 업로드 제한</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>이 사용자 강퇴</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>사용자</target>
<source>Username or email address</source>
<target>사용자명 혹은 이메일 주소</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>암호</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>로그인</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>암호 잊음</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>이메일</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>이메일 주소</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>계정 만들기</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target state="new">Username</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="new">User</target>
<source>Username or email address</source>
<target state="new">Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="new">Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="new">Forgot your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="new">Email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target state="new">Create an account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target state="new">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">My channels</target>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Min seer historikk</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">undertekster</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="new">Video quota</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="new">User</target>
<source>Username or email address</source>
<target state="new">Username or email address</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
<target state="new">Password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit><trans-unit id="892063502898494584" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="new">Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="new">Forgot your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target state="new">Email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="new">Email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">Create an account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<target state="new">No limit</target>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">ondertitels</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Videoquotum</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Oneindig <x id="START_TAG_NG-CONTAINER" ctype="x-ng-container" equiv-text="<ng-container>"/>( <x id="INTERPOLATION" equiv-text="{{ dailyUserVideoQuota | bytes: 0 }}"/> per dag) <x id="CLOSE_TAG_NG-CONTAINER" ctype="x-ng-container" equiv-text="</ng-container>"/></target>
<source>Federation</source>
<target state="translated">Federatie</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">volgers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Verban deze gebruiker</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Gebruiker</target>
<source>Username or email address</source>
<target>Gebruikersnaam of e-mailadres</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Wachtwoord</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Hier klikken om je wachtwoord opnieuw in te stellen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit><trans-unit id="892063502898494584" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Door in te loggen op een account, kunt u content publiceren</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Aanmelden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Of meld je aan met</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Jouw wachtwoord vergeten</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Het spijt ons, maar we kunnen je wachtwoord niet herstellen. De beheerder van je exemplaar van PeerTube heeft het PeerTube-emailsysteem niet ingesteld.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Je email-adres invoeren en je krijgt van ons instructies om je wachtwoord opnieuw in te stellen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-mailadres</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Herinstellen</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target>Account maken</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">VIDEO'S</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Ik ben een theepot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Dat is een fout.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Media te groot voor de server. Gelieve je beheerder te contacteren als je de groottelimiet wil verhogen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Sorry, uploaden is uitgeschakeld voor je account. Als je een video wil toevoegen, dan moet een beheerder je quotum ontgrendelen.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Naam volger</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Status</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Surpluskopie toegelaten <x id="START_TAG_P-SORTICON" ctype="x-p-sortIcon" equiv-text="<p-sortIcon>"/> <x id="CLOSE_TAG_P-SORTICON" ctype="x-p-sortIcon" equiv-text="</p-sortIcon>"/></target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Exemplaar van PeerTube openen in nieuwe tab</target>
<source>No host found matching current filters.</source>
<target state="translated">Geen host gevonden op basis van huidige filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Je exemplaar van PeerTube volgt niemand.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Nu te zien: <x id="INTERPOLATION" equiv-text="{{'{first}'}}"/> tot <x id="INTERPOLATION_1" equiv-text="{{'{last}'}}"/> van <x id="INTERPOLATION_2" equiv-text="{{'{totalRecords}'}}"/> hosts</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Domeinen volgen</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">vb. piet_fluwijn</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rol</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Transcoding is ingeschakeld. De videoquota houden enkel rekening met de grootte van de <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>originele <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> video. <x id="LINE_BREAK" ctype="lb" equiv-text="<br/>"/> Deze gebruiker kan maximaal ~ <x id="INTERPOLATION" equiv-text="{{ computeQuotaWithTranscoding() | bytes: 0 }}"/> uploaden. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="translated">Video met reacties</target>
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Het lijkt dat je niet op een HTTPS-server zit. Om een andere server te volgen is TLS op jouw webserver vereist.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Domeinen dempen</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Wil je echt <x id="PH"/> verwijderen? Dat verwijdert <x id="PH_1"/> video's die in dit kanaal geüpload zijn. Je kan ook geen nieuw kanaal meer maken met dezelfde naam. (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="translated">Mijn Kanalen</target>
<source>Your message has been sent.</source>
<target>Jouw bericht is verstuurd.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>U hebt dit formulier onlangs al verzonden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> directe accountvolgers </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Deze account melden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target>Gebruikersnaam gekopieerd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 abonnee</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> abonnees</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Exemplaren van PeerTube die je volgt</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Exemplaren van PeerTube die je volgen</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Enkel audio</target>
<source>Auto (via ffmpeg)</source>
<target>Automatisch (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<target state="translated">Onbeperkt</target>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Domein is vereist.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">De ingevoerde domeinen zijn ongeldig.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">De ingevoerde domeinen bevatten dubbels.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Oneindig</target>
<source><x id="PH"/> removed from instance followers </source>
<target><x id="PH"/> verwijderd uit volgers van dit exemplaar van PeerTube </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> is niet valide
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Volgverzoek(en) verstuurd!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Wil je echt <x id="PH"/> niet meer volgen?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Onvolgen</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Je volgt <x id="PH"/> niet meer.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>ingeschakeld</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Fout</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Standaardlogboeken</target>
<target>Update gebruikerswachtwoord</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Lijst van gevolgden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Lijst van volgers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Gebruiker <x id="PH"/> bijgewerkt.</target>
<target state="translated">Federatie</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Exemplaren van PeerTube die je volgt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Exemplaren van PeerTube die jou volgen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Videos zullen worden verwijderd, reacties als verwijderd gemarkeerd.</target>
<target>Zet E-mail als Geverifieerd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Je kan root niet verbannen.</target>
<source>Video channel <x id="PH"/> created.</source>
<target>Videokanaal <x id="PH"/> gemaakt.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Deze naam bestaat al op dit exemplaar van PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Videokanaal <x id="PH"/> bijgewerkt.</target>
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Typ alsjeblieft de weergavenaam van het videokanaal ( <x id="PH"/>) om te bevestigen</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Videokanaal <x id="PH"/> verwijderd.</target>
<source>Ownership change request sent.</source>
<target>Eigenaarsveranderingsaanvrag gestuurd.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Abonneren op account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Naar mijn abonnementen gaan</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Ga naar mijn videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Ga naar mijn imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Ga naar mijn kanalen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Kan OAuth Client-aanmeldinformatie niet ophalen: <x id="PH"/>. Vergewis je ervan dat je PeerTube (config/ map) juist hebt geconfigureerd, in het bijzonder het onderdeel "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Je moet opnieuw verbinden.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Sneltoetsen:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Incorrecte gebruikersnaam of wachtwoord.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Je account is geblokkeerd.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">gelijk welke taal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">verbergen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">vervagen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">weergeven</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Niet gekend</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Jouw wachtwoord is succesvol gereset!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Te veel pogingen. Probeer alstublieft opnieuw na <x id="PH"/> minuten.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Te vaak geprobeerd, probeer alstublieft later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Serverfout. Probeer later alstublieft weer.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Geabonneerd op alle huidige kanalen van <x id="PH"/>. U krijgt meldingen van al zijn of haar nieuwe video's.</target>
<target>Jouw video is geupload naar jouw account en is privé.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Maar geassocieerde data(tags, beschrijving...) zullen verloren raken, weet je zeker dat je deze pagina wilt verlaten?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Jouw video is nog niet geupload, weet je zeker dat je deze pagina wilt verlaten?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Uploaden</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>
<x id="PH"/> uploaden
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Video gepubliceerd.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Deze video is niet beschikbaar op dit exemplaar van PeerTube. Wil je doorverwezen worden naar het originele exemplaar <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Doorverwijzing</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Deze video bevat volwassen of expliciete inhoud. Weet je zeker dat je hem wilt kijken?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Volwassen of expliciete content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Volgende</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Annuleren</target>
<source>Autoplay is suspended</source>
<target state="translated">Automatisch afspelen is opgeschort</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Volledig scherm ingaan/uitgaan (vereist focus op afspeler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">De video afspelen/pauseren (vereist focus op de afspeler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">De video dempen of niet meer dempen (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Naar een percentage van de video springen: 0 is 0% and 9 is 90% (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Het volume verhogen (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Het volume verlagen (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Vooruitspringen in de video (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Achteruit springen in de video (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Afspelen versnellen (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Afspelen vertragen (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Frame per frame door de video navigeren (vereist focus op de speler)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Like de video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Crear</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">vidèo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="new">subtitles</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Quòta vidèo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<target>Federacion</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Fòrabandir aqueste utilizaire</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Utilizaire</target>
<source>Username or email address</source>
<target>Nom d’utilizaire o adreça electronica</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Senhal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Clicatz aquí per reïnicializar vòstre senhal</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Connexion</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Senhal oblidat</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">O planhèm, podètz pas restaurar lo senhal perque l'administrator de l'instància configurèt pas lo sistèm de corrièl de PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Corrièl</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Adreça de corrièl</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<target>Crear un compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Gestion dels seguidors</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Estatisticas</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Òst</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nom d’utilizaire</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Ròtle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Aqueste compte a pas cap de cadena.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target>Messatge enviat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Avètz ja enviat aqueste formulari fa pas gaire</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>Nom d’utilizaire copiat</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Las instàncias que seguissètz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Las instàncias que vos seguisson</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Àudio solament</target>
<source>Auto (via ffmpeg)</source>
<target>Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Un domeni es requerit.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Los domenis picats son pas valids.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Cap de limit</target>
<x id="PH"/> tirat dels seguidors de l’instància
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> es pas valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Demanda(s) de seguiment enviada !</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Volètz vertadièrament quitar de seguir
<x id="PH"/> ?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Quitar de seguir</target>
<target>Seguèt pas mai
<x id="PH"/>.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>activada</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target>Actualizar lo senhal de l’utilizaire</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Passar l’adreça coma verificada</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Podètz pas fòrabandir lo root.</target>
<target>Cadena vidèo
<x id="PH"/> creada.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Aqueste nom existís ja sus aquesta instància.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Cadena vidèo
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Volgatz ben picar lo nom public de la cadena vidèo (
- <x id="PH"/>) per dire de confirmar
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Cadena vidèo
<source>Ownership change request sent.</source>
<target>Demanda de cambiament de proprietat enviada.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>S’abonar al compte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Anar a mos abonaments</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Anar a mas vidèos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Anar a mos imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Anar a ma cadena</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Vos cal vos reconnectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Acorchis clavièr :</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Nom d’utilizaire o senhal incorrècte.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">tota lenga</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">amagar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">mostrar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Vòstre senhal es estat corrèctament reïnicializat !</target>
<target>Tròp d’ensages, mercés de tornar ensajar dins
<x id="PH"/> minutas.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Tròp d’ensages, mercés de tornar ensajar mai tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Error servidor. Mercés de tornar ensajar mai tard.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>La vidèo es estada enviada a vòstre compte e es privada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Mas las donadas associadas (etiquetas, descripcion...) seràn perdudas, volètz vertadièrament quitar la pagina ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>La vidèo es pas encara complètament enviada, volètz vertadièrament quitar la pagina ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Enviar
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vidèo publicada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Avètz de modificacions pas enregistradas. Se partissètz vòstras modificacions seràn perdudas. </target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Aquesta vidèo conten un contengut per adult o explicite. Volètz vertadièrament la veire ?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Contengut per adult o explicite</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Seguent</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="translated">La lectura automatica es suspenduda</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Aimar la vidèo</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Moja historia oglądania</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Utwórz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">film</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Następujący odnośnik zawiera prywatny token i nie należy się nim z nikim dzielić.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Twoja powierzchnia na filmy została przekroczona przez ten film (rozmiar filmu: <x id="PH" equiv-text="videoSizeBytes"/>, wykorzystano: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, powierzchnia: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Twoja dzienna powierzchnia na filmy została przekroczona przez ten film (rozmiar filmu: <x id="PH" equiv-text="videoSizeBytes"/>, wykorzystano: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, powierzchnia <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">napisy</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Przestrzeń na filmy</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Nieograniczony
<target state="translated">Federacja</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Anuluj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="translated">Zbanuj tego użytkownika</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Ta knstancja pozwala na rejestrację. Pamiętaj jednak sprawdzić <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Zasady<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Zasady<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> przed utworzeniem konta. Możesz też odnaleźć inną instancję spełniającą Twoje oczekiwania na: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/pl/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/pl/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Obecnie ta instancja nie pozwala na rejestrację użytkowników, możesz sprawdzić <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Zasady<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>, aby znaleźć więcej szczegółów lub znaleźć instancję, która pozwoli Ci na rejestrację konta i wysyłanie własnych filmów. Znajdź swoją spośród wielu instancji na: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/pl/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/pl/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Użytkownik</target>
<source>Username or email address</source>
<target>Nazwa użytkownika lub adres e-mail</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Hasło</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Kliknij tutaj aby zresetować swoje hasło</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Nie pamiętam hasła</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Logowanie na konto pozwala na publikację treści</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Zaloguj się</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Lub zaloguj się z</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Zapomniałem hasła</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Przepraszamy, nie możesz odzyskać hasła ponieważ administrator twojej instancji nie skonfigurował systemu e-mail.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Wprowadź swój adres e-mail, a my wyślemy link pozwalający na zresetowanie hasła.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Adres e-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Resetuj</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">na tej instancji</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Utwórz konto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Moje filmy</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">FILMY</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Równoczesne zadania importu</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Jestem czajniczkiem</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">To błąd.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Zawartość multimedialna jest zbyt wielka dla tego serwerami skontaktuj się z administratorem, jeżeli chcesz aby zwiększył limit rozmiaru.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">WYSZUKIWANIE OGÓLNE</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Niestety, możliwość wysyłania jest wyłączona dla Twojego konta. Jeżeli chcesz dodać filmy, administrator musi odblokować Twój przydział powierzchni.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Nazwa obserwującego użytkownika</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target state="translated">Stan</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundancja zezwolona
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Przestań obserwować</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Otwórz instancję w nowej karcie</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Brak hostów spełniających obecne kryteria.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Twoja instancja nie obserwuje nikogo.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Wyświetlanie <x id="INTERPOLATION"/> do <x id="INTERPOLATION_1"/> z <x id="INTERPOLATION_2"/> hostów</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Obserwuj domeny</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Zaobserwuj instancje</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Działanie</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nazwa użytkownika</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">np. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Rola</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Transkodowanie jest włączone. Limit użytej powierzchni bierze pod uwagę tylko <x id="START_TAG_STRONG"/>oryginalny<x id="CLOSE_TAG_STRONG"/> rozmiar filmów. <x id="LINE_BREAK"/> Maksymalnie, użytkownik może wysłać~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Wtyczka uwierzytelniania</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Brak (lokalne uwierzytelnianie)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Wygląda na to, że nie jesteś na serwerze HTTPS. Twój serwer musi mieć aktywne TLS, aby obserwować inne serwery.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Wycisz domeny</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">KANAŁY</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">To konto nie ma kanałów.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Czy na pewno cchesz usunąć <x id="PH" equiv-text="videoChannel.displayName"/>? Usuniesz w ten sposób <x id="PH_1" equiv-text="videoChannel.videosCount"/> filmów wysłanych na ten kanał i nie będziesz miał(a) możliwości założenia kanału o tej samej nazwie (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>Twoja wiadomość została wysłana.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">Niedawno wypełniłeś(-aś) ten formularz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Filmy konta</target>
<target state="translated">
<x id="PH"/> bezpośrednio obserwujących konto
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Zgłoś to konto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">FILMY</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Nazwa użytkownika skopiowana</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 subskrybujący</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> subskrybujący</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancje, które obserwujesz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancje, które Cię obserwują</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Tylko dźwięk</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Automatycznie (poprzez ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Domena jest wymagana.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Wprowadzone domeny są nieprawidłowe.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Wprowadzone domeny zawierają duplikaty.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Nieograniczona</target>
<x id="PH"/> usunięty z obserwujących instancję
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> nie jest prawidowy
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Wysłano prośby o możliwość śledzenia!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Czy na pewno chcesz przestać śledzić
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Przestań śledzić</target>
<target>Już nie śledzisz
<x id="PH"/>.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="translated">włączona</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Błąd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Standardowe raporty</target>
<target state="translated">Zaktualizuj hasło użytkownika</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Lista obserwujących</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Lista obserwowanych</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Aktualizowano użytkownika <x id="PH"/>.</target>
<target state="translated">Federacja</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instancje które obserwujesz</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instancje które Cię obserwują</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Filmy zostaną usunięte, komentarze zostaną porzucone.</target>
<target state="translated">Ustaw e-mail jako zwerifykowany</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target>Utworzono kanał wideo
<x id="PH"/>.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Ta nazwa już istnieje na tej instancji.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Zaktualizowano kanał wideo
<target state="translated">Usunięto baner.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Wpisz nazwę kanału (
- <x id="PH"/>) aby potwierdzić
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Usunięto kanał wideo
<source>Ownership change request sent.</source>
<target state="translated">Wysłano prośbę o zmianę właściciela.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target state="translated">Subskrybuj to konto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">PLAYLISTY</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Przejdź do moich subskrypcji</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Przejdź do moich filmów</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Przejdź do moich importów</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Przejdź do moich kanałów</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Nie można uzyskać danych uwierzytelniających klienta OAuth: <x id="PH" equiv-text="error.text"/>. Upewnij się, że PeerTube jest prawidłowo skonfigurowane (katalog config/), szczególnie w sekcji „webserver”.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Musisz połączyć się ponownie.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Skróty klawiaturowe:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">Nieprawidłowa nazwa użytkownika lub hasło.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Twoje konto jest zablokowane</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">jakikolwiek język</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">ukryj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">rozmazanie</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">wyświetl</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Nieznane</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Pomyślnie zresetowano hasło!</target>
<target>Zbyt wiele prób, spróbuj ponownie za
<x id="PH"/> minut.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Zbyt wiele prób, spróbuj ponownie później.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Błąd serwera. Spróbuj ponownie później.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Zasubskrybowano wszystkie kanały użytkownika
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">Film został wrzucony na twoje konto i jest prywatny.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Powiązane dane (tagi, opis…) zostaną utracone, czy na pewno chcesz opuścić tą stronę?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Twój film nie został jeszcze wysłany, czy na pewno chcesz opuścić tą stronę?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Wyślij</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Wrzuć
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Opublikowano film.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="translated">Masz niezapisane zmiany! Jeżeli zamkniesz to okno, twoje zmiany zostaną stracone.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Ten film nie jest dostępny na tej instancji. Czy chcesz zostać przekierowany(-a) na instancję źródłową: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Przekierowanie</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Ten film zawiera treści wulgarne lub przeznaczone dla dorosłych. Czy na pewno chcesz go obejrzeć?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Zawartość wulgarna lub dla dorosłych</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Następnie</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Anuluj</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Automatyczne odtwarzanie jest zatrzymane</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Włącz/wyłącz tryb pełnoekranowy (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Odtwarzaj/spauzuj film (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Wycisz/wyłącz wyciszenie filmu (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Przeskocz do procentowej części filmu: 0 to 0% i 9 to 90% (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Zwiększ głośność (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Zmniejsz głośność (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Przeskocz dalej w filmie (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Przeskocz do tyłu w filmie (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Przyspiesz odtwarzanie (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Zwolnij odtwarzanie (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Przeglądaj film klatka po klatce (kiedy zaznaczony jest odtwarzacz)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">Zaznacz "Lubię to"</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Criar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">subtítulos</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Quota de vídeo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<target state="translated">Federação</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Banir este usuário</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Usuário</target>
<source>Username or email address</source>
<target>Nome de usuário ou endereço de e-mail</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Senha</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Clique aqui para redefinir sua senha</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Entrar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Esqueceu sua senha</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Lamentamos, não podemos recuperar sua senha porque o administrador dessa instância não ativou o envio de e-mail pelo PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Endereço de e-mail</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<target>Criar uma conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Identificador de inscritos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Estado</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundância permitida
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Abrir instância em uma nova aba</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Nenhum host encontrado correspondendo aos filtros atuais.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Sua instância não possui seguidores.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Mostrando
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Seguir domínios</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Nome de usuário</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Papel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">A transcodificação está habilitada. A quota de vídeo só leva em consideração o tamanho do vídeo
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Essa conta não possui canais.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target>Sua mensagem foi enviada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Você já enviou este formulário recentemente</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Nome de usuário copiado</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Áudio-somente</target>
<source>Auto (via ffmpeg)</source>
<target>Automático (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Ilimitado</target>
<x id="PH"/> removido dos seguidores da sua instância
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> não é válido
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Solicitação de seguir(s) enviada!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Você realmente deseja parar de seguir <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Parar de seguir</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Você não está mais seguindo <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>habilitado</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Erro</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Registros padrões</target>
<target>Atualizar senha do usuário</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>Definir Email como Confirmado</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Você não pode banir root.</target>
<target>Canal de vídeo
<x id="PH"/> criado.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Este nome já existe nesta instância.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Canal de vídeo
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Por favor, digite o nome de exibição do canal (
- <x id="PH"/>) para confirmar
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Canal de vídeo
<source>Ownership change request sent.</source>
<target>Solicitação para mudar dono enviada.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Inscreva-se na conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Ir às minhas inscrições</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Ir aos meus vídeos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Ir às minhas importações</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Ir aos meus canais</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>você precisa se reconectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Atalhos de teclado:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Nome de usuário ou senha incorretos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Sua conta foi bloqueada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Sua senha foi redefinida com sucesso!</target>
<target>Muitas tentativas, por favor tente novamente depois de
<x id="PH"/> minutos.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Muitas tentativas, por favor tente novamente depois.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Erro de servidor. Por favor, tente novamente depois.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Inscrito em todos os canais atuais de
<source>Your video was uploaded to your account and is private.</source>
<target>Seu vídeo foi enviado para sua conta e é privado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Mas dados associados (tags, descrição…) serão perdidas, tem certeza que deseja sair dessa página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Seu vídeo ainda não foi atualizado, você tem certeza que deseja sair dessa página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Subir
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vídeo publicado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Você tem modificações não salvas! Se sair desta páginas, as modificações serão perdidas.</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Este vídeo possui conteúdo adulto ou explícito. Você tem certeza que deseja assisti-lo?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Conteúdo adulto ou explícito</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Seguinte</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="translated">Auto-leitura está suspensa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Entrar/Sair da tela cheia (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Tocar/Pausar o vídeo (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Silenciar/Pôr som no vídeo (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Pular para uma percentagem do vídeo: 0 é 0% e 9 é 90% (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Aumentar o volume (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Reduzir o volume (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Procure o vídeo para frente (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Procure o vídeo para trás (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Aumenta a taxa de reprodução (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Diminuir a taxa de reprodução (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navegue no vídeo quadro por quadro (requer foco do leitor)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Gostar do vídeo</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Ilimitado
<source>Federation</source>
<target state="translated">Federação</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">seguidores</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Banir este utilizador</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Utilizador</target>
<source>Username or email address</source>
<target>Nome de utilizador ou endereço de correio eletrónico</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Clique aqui para redefinir a sua senha</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Iniciar sessão</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Esqueceu-se da sua palavra-passe</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Endereço de correio eletrónico</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target>Criar uma conta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Estado</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Abre instância numa nova tabulação</target>
<source>No host found matching current filters.</source>
<target state="translated">Não encontrou algum host que corresponda aos filtros actuais.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">A sua instância não está a seguir alguém.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Siga domínios</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target>Papel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Transcodificação está activada. A quota de vídeos tem em conta apenas o tamanho de vídeo
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Parece que não está em um servidor HTTPS. O seu servidor necessita de ter TLS activado para conseguir seguir outros servidores.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Silenciar domínios</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Ilimitado</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895">
<source>
<x id="PH"/> is not valid
<x id="PH"/> não é válido
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Solicitação de seguir(s) enviada!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Você realmente deseja parar de seguir
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Parar de seguir</target>
<x id="PH"/>.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target state="new">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target state="new">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>Você não pode banir root.</target>
<x id="PH"/> criado.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Canal de vídeo
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Canal de vídeo
<source>Ownership change request sent.</source>
<target>Solicitação para mudar dono enviada.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Meus canais</target>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>você precisa se reconectar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target>Nome de usuário ou senha incorretos.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Sua senha foi redefinida com sucesso!</target>
<x id="PH"/> minutos.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Muitas tentativas, por favor tente novamente depois.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Erro de servidor. Por favor, tente novamente depois.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target>Seu vídeo foi enviado para sua conta e é privado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Mas dados associados (tags, descrição…) serão perdidas, tem certeza que deseja sair dessa página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Seu vídeo ainda não foi atualizado, você tem certeza que deseja sair dessa página?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Vídeo publicado.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Este vídeo possui conteúdo adulto ou explícito. Você tem certeza que deseja assisti-lo?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Conteúdo adulto ou explícito</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target state="new">Like the video</target>
<trans-unit id="187187500641108332" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Моя история просмотров</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Создать</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">видео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Следующая ссылка содержит личный токен и никому не может быть передана.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Ваша квота для этого видео превышена (размер видео: <x id="PH" equiv-text="videoSizeBytes"/>, использовано: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, квота: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Ваша дневная квота для этого видео превышена (размер видео: <x id="PH" equiv-text="videoSizeBytes"/>, использовано: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, квота: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">субтитры</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Квота на видео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Неограниченно <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> в день)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Федерация</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Отменить</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Заблокировать этого пользователя</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Этот экземпляр разрешает регистрацию. Однако будьте осторожны, проверьте <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Условия пользования<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> перед созданием учетной записи. Вы также можете найти другой экземпляр, который точно соответствует вашим потребностям, на: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">В настоящее время этот экземпляр не позволяет регистрировать пользователей, проверьте <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Условия пользования<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> для получения дополнительных сведений, или найдите экземпляр, который дает вам возможность зарегистрировать учетную запись и загружать туда свои видео. Найдите свой среди множества экземпляров на: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Пользователь</target>
<source>Username or email address</source>
<target>Имя пользователя или электронный адрес</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Нажмите здесь что бы сбросить пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Я забыл свой пароль</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Авторизация учетной записи позволяет публиковать контент</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Авторизация</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Или войдите с помощью</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Забыли пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">К сожалению, вы не можете восстановить свой пароль, так как администратор вашего экземпляра не настроил почтовую систему PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Введите свой email и мы пришлём вам ссылку для сброса пароля.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Email адрес</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Сброс</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">на этом экземпляре</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Создать учетную запись</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Мои видео</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">ВИДЕО</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Параллельный импорт заданий</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Я чайник</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Это ошибка.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Видео слишком большое для сервера. Пожалуйста свяжитесь со вашим администратором для увеличение лимита.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">ГЛОБАЛЬНЫЙ ПОИСК</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Загрузка приостановлена</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Извините, загрузка файлов недоступна для вашей учётной записи. Если вы хотите добавлять видео, свяжитесь с администратором.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Подписчик</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Состояние</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Хост</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Избыточность разрешена <x id="START_TAG_P-SORTICON"/> <x id="CLOSE_TAG_P-SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Отписаться</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Открыть экземпляр в новой вкладке</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Не найдено ни одного хоста, соответствующего текущим фильтрам.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Ваш экземпляр ни за кем не подписан.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Показано <x id="INTERPOLATION"/> по <x id="INTERPOLATION_1"/> из <x id="INTERPOLATION_2"/> хостов</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Следить за доменами</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Следить за экземплярами</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Действие</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Имя пользователя</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">прим. ivan_ivanov</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Роль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Транскодирование включено. Квота видео учитывает только <x id="START_TAG_STRONG"/>оригинальный<x id="CLOSE_TAG_STRONG"/> размер видео. <x id="LINE_BREAK"/>Максимум, этот пользователь мог загрузить ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Плагин авторизации</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Нет (локальная аутентификация)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Похоже, вы не на сервере HTTPS. На вашем веб-сервере должен быть активирован TLS, чтобы следить за серверами.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Отключить домены</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">КАНАЛЫ</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Эта учетная запись не имеет каналов.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Вы действительно хотите удалить <x id="PH" equiv-text="videoChannel.displayName"/>? Будет удалено <x id="PH_1" equiv-text="videoChannel.videosCount"/> видео загруженное на этот канал, и вы не сможете создать другой канал с таким же именем (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>Ваше сообщение было отправлено.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Вы уже отправили эту форму совсем недавно</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Видео аккаунта</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> прямые подписчики аккаунта </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Пожаловаться на этот аккаунт</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">ВИДЕО</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Имя пользователя скопировано</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 подписчик</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> подписчиков</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Экземпляры, за которыми вы следите</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Следующие за вами экземпляры</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Только для аудио</target>
<source>Auto (via ffmpeg)</source>
<target>Авто (используя ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Требуется домен.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Введенные домены недействительны.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Введенные домены содержат дубликаты.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Неограниченно</target>
<x id="PH"/> удалено из последователей экземпляра
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> недействителен
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Запрос (ы) на подписку отправлены!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Вы действительно хотите отписаться от <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Отписаться</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Вы больше не подписаны на <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>включено</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Ошибка</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Стандартные журналы</target>
<target>Изменить пароль пользователя</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Следующий список</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Список подписчиков</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Пользователь <x id="PH"/> обновлён.</target>
<target state="translated">Федерация</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Экземпляры, за которыми вы следите</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Экземпляры подписанные на вас</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Видео будет удалено, комментарии будут заморожены.</target>
<target>Пометить электронную почту как подтверждённую</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Видеоканал <x id="PH"/> был создан.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Данное название уже занято на этом сервере.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Видеоканал <x id="PH"/> обновлён.</target>
<target state="translated">Баннер удален.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Пожалуйста, напишите название канала ( <x id="PH"/>) для подтверждения</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Видеоканал <x id="PH"/> был удалён.</target>
<source>Ownership change request sent.</source>
<target>Заявка на смена владельца отправлена.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Подписаться на аккаунт</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">ПЛЕЙЛИСТЫ</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Перейти на мои подписки</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Перейти на мои видео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Перейти на мои импортированные видео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Перейти на мои каналы</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Не удается получить учетные данные клиента OAuth: <x id="PH" equiv-text="error.text"/>. Убедитесь, что вы правильно настроили PeerTube (config / directory), в частности раздел «веб-сервер».</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Вам необходимо переподключиться.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Комбинации клавиш:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Неверное имя пользователя или пароль.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Ваш аккаунт заблокирован.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">любой язык</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">скрыть</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">размытие</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">отображение</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Неизвестно</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Ваш пароль был успешно сброшен!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>Слишком много попыток, пожалуйста, попробуйте снова через <x id="PH"/> минут.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Слишком много попыток, пожалуйста, попробуйте ещё раз позже.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Ошибка сервера. Пожалуйста, повторите попытку позже.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Подписан на все текущие каналы <x id="PH"/>. Вы будете уведомлены обо всех их новых видео.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Ваше видео было загружено на ваш аккаунт и является приватным.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Но связанные данные (теги, описание...) будут потеряны, вы уверены, что хотите покинуть эту страницу?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Ваше видео еще не загружено, вы уверены, что хотите покинуть эту страницу?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Загрузить</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">Загрузить <x id="PH"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Видео опубликовано.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>У вас есть несохраненные изменения! Если вы уйдете, ваши изменения будут потеряны.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Это видео недоступно в этом экземпляре. Вы хотите, чтобы вас перенаправили на исходный экземпляр: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Перенаправление</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Это видео содержит зрелый или откровенный контент. Вы уверены, что хотите посмотреть его?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Зрелый или откровенный контент</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Следующий</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Отмена</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Автовоспроизведение приостановлено</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Вход / выход в полноэкранный режим (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Воспроизвести / приостановить видео (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Отключить / включить видео (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Переход к проценту от видео: 0 - 0%, 9 - 90% (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Увеличьте громкость (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Уменьшить громкость (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Искать видео вперед(требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Искать видео в обратном направлении (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Увеличить скорость воспроизведения(требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Уменьшить скорость воспроизведения (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Navigate in the video frame by frame (требуется фокус проигрывателя)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Мне понравилось</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="new">User</target>
<source>Username or email address</source>
<target state="new">Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429" datatype="html">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="new">Login</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="new">Forgot your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="new">Email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target state="new">Create an account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target state="new">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">My channels</target>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="new">subtitles</target>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<target state="new">Video quota</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="new">Ban this user</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729" datatype="html">
<source>User</source>
<target state="new">User</target>
<source>Username or email address</source>
<target>Uporabniško ime ali e-poštni naslov</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Geslo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Prijava</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Ste pozabili geslo?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-poštni naslov</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-poštni naslov</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="new">on this instance</target>
<target>Ustvari račun</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target state="new">Username</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="new">This account does not have channels.</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<target state="new">Video channel
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="new">PLAYLISTS</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Min visningshistorik</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Skapa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Följande länk innehåller en personlig nyckel och bör ej delas med någon annan.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Din videokvot kommer överskridas av den här videon (videostorlek: <x id="PH" equiv-text="videoSizeBytes"/>, använt: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, kvot: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Din dagliga videokvot kommer överskridas av den här videon (videostorlek: <x id="PH" equiv-text="videoSizeBytes"/>, använt: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, kvot:<x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">undertexter</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Videokvot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>Obegränsat <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per dag)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target>Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Avbryt</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Blockera den här användaren</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Den här instansen tillåter kontoregistrering. Se till att läsa <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>villkoren<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>villkoren<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> innan du skapar ett konto. Du kan också söka efter en annan instans som passar dina behov bättre på <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Den här instansen tillåter inte kontoregistrering för närvarande, men du kan läsa <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>villkoren<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> för mer information eller hitta en annan instans som ger dig möjligheten att skaffa ett konto och ladda upp dina videor där. Hitta din instans av dem alla på <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Användare</target>
<source>Username or email address</source>
<target>Användarnamn eller e-postadress</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Lösenord</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Klicka här för att återställa ditt lösenord</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Jag har glömt mitt lösenord</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Du måste logga in för att kunna publicera material</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Logga in</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Eller logga in med</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Glömt ditt lösenord</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target>
Du kan inte återställa ditt lösenord eftersom din instans administratör inte har konfigurerat PeerTubes e-postsystem.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Ange din e-postadress så skickar vi dig en länk för att återställa till lösenord.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>E-post</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>E-postadress</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Återställ</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">på den här instansen</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Skapa ett konto</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Mina videor</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOR</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Samtidiga importjobb</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Jag är en tekanna</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Detta är ett fel.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Filen är för stor för servern. Kontakta din administratör om du vill höja gränsen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">GLOBAL SÖKNING</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Uppladdning pausad</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Uppladdning är inte aktiverat från ditt konto. Om du vill lägga upp videor, måste en administratör låsa upp din videokvot.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>Hantera följare</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Status</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>Värd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Redundans tillåten <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Sluta följa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Öppna instansen i en ny flik</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Inga värdar matchar de nuvarande filtren.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Din instans följer inte någon annan.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Visar värd <x id="INTERPOLATION"/> till <x id="INTERPOLATION_1"/> av <x id="INTERPOLATION_2"/></target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Följ domäner</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Följ instanser</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Åtgärd</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Användarnamn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">t.ex. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Roll</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Omkodning har aktiverats. Videokvoten omfattar endast <x id="START_TAG_STRONG"/>originalfilens<x id="CLOSE_TAG_STRONG"/> storlek. <x id="LINE_BREAK"/> Den här användaren kan ladda upp ungefär <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Tillägg för autentisering</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Ingen (lokal autentisering)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Det verkar som att din server inte använder HTTPS. Webbserver måste ha TLS aktiverat för att följa andra servrar.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Ignorera instanser</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">KANALER</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>Det här kontot har inga kanaler.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Vill du verkligen radera <x id="PH" equiv-text="videoChannel.displayName"/>? Det kommer att radera <x id="PH_1" equiv-text="videoChannel.videosCount"/> videor uppladdade till kanalen, och du kan inte skapa en kanal med samma namn (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>Ditt meddelande har skickats.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>Du har redan skickat detta formulär nyligen</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Kontots videor</target>
<target state="translated">Kontot har
<x id="PH"/> direktföljare
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Anmäl det här kontot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEOR</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>Användarnamn kopierat</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 prenumerant</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> prenumeranter</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instanser du följer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instanser som följer dig</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Endast ljud</target>
<source>Auto (via ffmpeg)</source>
<target>Automatiskt (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Domän måste uppges.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Angivna domäner är ogiltiga.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Domänerna innehåller dubbletter.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>Obegränsat</target>
<x id="PH"/> har tagits bort från listan över instansföljare
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> är inte giltig
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>Följningsförfrågan / förfrågningar skickad!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>Vill du verkligen sluta följa <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>Sluta följa</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>Du följer inte <x id="PH"/> längre.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>aktiverad</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>Fel</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Standardloggar</target>
<target>Uppdatera användarens lösenord</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Lista över följda instanser</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Lista över följare</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Användaren <x id="PH"/> uppdaterad.</target>
<target state="translated">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Instanser du följer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Instanser som följer dig</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Videorna kommer raderas och kommentarerna arkiverade.</target>
<target>Markera e-post som verifierad</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>Kanalen <x id="PH"/> har skapats.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>Namnet finns redan på den här instansen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>Kanalen <x id="PH"/> har uppdaterats.</target>
<target state="translated">Baneret har raderats.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>Uppge kanalens visningsnamn (<x id="PH"/>) för att bekräfta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>Kanalen <x id="PH"/> har raderats.</target>
<source>Ownership change request sent.</source>
<target>Förfrågan om byte av ägarskap har skickats.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>Prenumerera på kontot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">SPELLISTOR</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>Gå till mina prenumerationer</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>Gå till mina videor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>Gå till mina importeringar</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>Gå till mina kanaler</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Kan inte hämta OAuth Client-uppgifter: <x id="PH" equiv-text="error.text"/>. Försäkra dig om att du har konfigurerat PeerTube korrekt (i config-katalogen), speciellt ”webserver”-sektionen.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>Du måste återansluta.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Kortkommandon:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>Felaktigt användarnamn eller lösenord.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Ditt konto har blockerats.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">vilket språk som helst</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">dölj</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">gör suddig</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">visa</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Okänd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>Ditt lösenord har återställts!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>För många försök, vänligen försök igen om <x id="PH"/> minuter.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>För många försök, vänligen försök igen senare.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Serverfel, försök gärna igen om en stund.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Prenumererar på samtliga kanaler tillhörande <x id="PH"/>. Du kommer underrättas om alla nya videor.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Din video har laddats upp till ditt konto och är privat.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Men associerad data (taggar, beskrivning …) kommer försvinna, är du säker på att du vill lämna sidan?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Din video har inte laddats upp än, vill du lämna sidan?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Ladda upp</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Ladda upp
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Videon har publicerats.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Du har gjort ändringar som inte sparats! Om du lämnar nu kommer de förkastas.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Den här videon finns inte på din instans. Vill du bli hänvisad till ursprungsinstansen <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Omdirigering</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Den här videon innehåller oförbehållsamt innehåll eller innehåll skapat för vuxna. Är du säker på att du vill se den?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Oförbehållsamt innehåll eller innehåll skapat för vuxna</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Kommer härnäst</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Avbryt</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Automatisk uppspelning är upphävd</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Slå av eller på helskärmsläget (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Spela eller pausa videon (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Slå av eller på ljudet (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Hoppa till en position i videon: 0 motsvarar 0 % av den totala speltiden och 9 motsvarar 90 % (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Öka volymen (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Minska volymen (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Spola videon framåt (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Spola videon bakåt (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Öka uppspelningshastigheten (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Minska uppspelningshastigheten (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Föregående eller nästkommande bildruta (spelaren måste vara markerad)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Gilla videon</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit><trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source><target state="new">My watch history</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-history/my-history.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="new">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit><trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source><target state="new">subtitles</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source> Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>இந்த பயணரை ரத்து செய்</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html</context><context context-type="linenumber">16</context></context-group></trans-unit><trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit><trans-unit id="7215649348148521605" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source><target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>பயணர்</target>
<source>Username or email address</source>
<target state="new">Username or email address</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="new">Click here to reset your password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source><target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit><trans-unit id="2101170466365500913" datatype="html">
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit><trans-unit id="2101170466365500913" datatype="html">
<source> Logging into an account lets you publish content </source><target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>உள்நுழை</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="new">Or sign in with</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>கடவுச்சொல் மறந்துவிட்டது</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source><target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit><trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</source><target state="new">An email with the reset password instructions will be sent to <x id="PH"/>.
The link will expire within 1 hour.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>மின்னஞ்சல்</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit><trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source><target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>Create an account</source>
<target>கணக்கை உருவாக்கு</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source><target state="new">My videos</target>
<target state="new">VIDEOS</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/menu/notification.component.html</context><context context-type="linenumber">49</context></context-group></trans-unit><trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source><target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit><trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source><target state="new">That's an error.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context>
<context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.html</context><context context-type="linenumber">42</context></context-group></trans-unit><trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source><target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group></trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source><target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit><trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source><target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit><trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source><target state="new">e.g. jane_doe</target>
<note priority="1" from="description">Username choice placeholder in the registration form</note>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source> Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="4691552465058437520" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit><trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source><target state="new">Commented video</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">82</context></context-group></trans-unit><trans-unit id="7266085473379376028" datatype="html">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source><target state="new">Account videos</target>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit><trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source><target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source><target state="new">VIDEOS</target>
<target state="new">Username copied</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit><trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source><target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit><trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source><target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="931255636742351800" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit><trans-unit id="931255636742351800" datatype="html">
<source>No limit</source><target state="new">No limit</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-live-configuration.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit><trans-unit id="5250062810079582285" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group></trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source>
<x id="PH"/> is not valid
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<source>Update user password</source>
<target state="new">Update user password</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit><trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source><target state="new">Following list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group></trans-unit><trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source><target state="new">Followers list</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group></trans-unit>
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/users.routes.ts</context><context context-type="linenumber">45</context></context-group></trans-unit><trans-unit id="8564701209009684429" datatype="html">
<source>Federation</source><target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit><trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source><target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group></trans-unit><trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source><target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group></trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">My channels</target>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit><trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source><target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit><trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source><target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload
<x id="PH"/>
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source><target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit><trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source><target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit><trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source><target state="new">Cancel</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">646</context></context-group></trans-unit>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<target state="new">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="new">My watch history</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>สร้าง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">วิดีโอ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">คำบรรยายใต้ภาพ</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>ปริมาณวิดีโอที่สามารถอัปโหลดได้</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>
<target state="translated">รวมเว็บไซต์อื่น</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>ยกเลิก</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>แบนผู้ใช้นี้</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">เซิร์ฟเวอร์นี้เปิดให้ลงทะเบียนผู้ใช้ใหม่ อย่างไรก็ตาม โปรดตรวจสอบ<x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>เงื่อนไข<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>เงื่อนไข<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>อย่างระมัดระวังก่อนการสร้างบัญชี คุณสามารถหาเซิร์ฟเวอร์อื่นที่ตรงกับความต้องการของคุณโดยเฉพาะได้ที่: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">ณ ตอนนี้ เซิร์ฟเวอร์นี้ไม่เปิดให้ลงทะเบียนผู้ใช้ใหม่ คุณสามารถตรวจสอบ<x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>เงื่อนไข<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>เพื่อดูข้อมูลเพิ่มเติมหรือหาเซิร์ฟเวอร์อื่นที่ให้คุณสร้างบัญชีและอัปโหลดวิดีโอได้ หาเว็บไซต์ที่เหมาะกับคุณได้ที่: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>ผู้ใช้</target>
<source>Username or email address</source>
<target>ชื่อผู้ใช้หรือที่อยู่อีเมล</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>รหัสผ่าน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">คลิกที่นี่เพื่อรีเซ็ตรหัสผ่าน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">ฉันลืมรหัสผ่าน</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">การเข้าสู่ระบบทำให้คุณสามารถเผยแพร่เนื้อหา</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>เข้าสู่ระบบ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">หรือเข้าสู่ระบบด้วย</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>ลืมรหัสผ่าน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">ขออภัย คุณไม่สามารถกู้คืนรหัสผ่านของคุณเนื่องจากผู้ดูแลระบบไม่ได้ตั้งค่าระบบอีเมล PeerTube</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">ใส่ที่อยู่อีเมลของคุณ เราจะส่งลิงก์เพื่อรีเซ็ตรหัสผ่านของคุณทางอีเมล</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>อีเมล</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>ที่อยู่อีเมล</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">รีเซ็ต</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">บนเซิร์ฟเวอร์นี้</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>สร้างบัญชีผู้ใช้</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">วิดีโอของฉัน</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">วิดีโอ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">ฉันเป็นกาน้ำชา</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">เกิดข้อผิดพลาด</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">สื่อมีขนาดใหญ่เกินที่จะอยู่บนเซิร์ฟเวอร์ โปรดติดต่อผู้ดูแลระบบหากคุณต้องการเพิ่มขีดจำกัดขนาด</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">ค้นหาทุกเซิร์ฟเวอร์</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">ขออภัย คุณสมบัติการอัปโหลดถูกปิดใช้งานสำหรับบัญชีของคุณ หากคุณต้องการเพิ่มวิดีโอ ผู้ดูแลระบบต้องปลดล็อกโควต้าของคุณก่อน</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>ชื่อผู้ใช้</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="translated">หน้าที่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">ช่อง</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">บัญชีนี้ไม่มีช่อง</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target state="translated">ข้อความของคุณถูกส่งแล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">คุณเพิ่งส่งฟอร์มนี้ไปเมื่อสักครู่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">วิดีโอในบัญชี</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">รายงานบัญชีนี้</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">วิดีโอ</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">คัดลอกชื่อผู้ใช้แล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated">ผู้ติดตาม <x id="PH"/> คน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">เฉพาะเสียง</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">อัตโนมัติ (ผ่าน ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">ไม่จำกัด</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">ข้อผิดพลาด</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">ช่องวิดีโอ <x id="PH"/> ถูกสร้างแล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">ชื่อนี้มีอยู่ในเซิร์ฟเวอร์นี้แล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">อัปเดตช่องวิดีโอ <x id="PH"/> แล้ว</target>
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">กรุณาพิมพ์ชื่อแสดงของช่อง ( <x id="PH"/>) เพื่อยืนยัน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">ลบช่องวิดีโอ <x id="PH"/> แล้ว</target>
<source>Ownership change request sent.</source>
<target state="translated">ส่งคำขอเปลี่ยนเจ้าของแล้ว</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">ติดตามบัญชี</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">เพลย์ลิสต์</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">ไปที่การติดตามของฉัน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">ไปที่วิดีโอของฉัน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">ไปที่การนำเข้าของฉัน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">ไปที่ช่องของฉัน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">คุณต้องเชื่อมต่อใหม่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">ปุ่มลัดคีย์บอร์ด:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">บัญชีของคุณถูกบล็อก</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">ภาษาใดก็ได้</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">ซ่อน</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">เบลอ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">แสดง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">ไม่รู้จัก</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">รีเซ็ตรหัสผ่านเรียบร้อย</target>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">พยายามหลายครั้งติดต่อกัน โปรดลองอีกครั้งในอีก <x id="PH"/> นาที</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="translated">พยายามหลายครั้งติดต่อกัน โปรดลองอีกครั้งในภายหลัง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="translated">เซิร์ฟเวอร์เกิดข้อผิดพลาด โปรดลองอีกครั้งในภายหลัง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">ติดตามทุกช่องในปัจจุบันของ <x id="PH"/> แล้ว คุณจะได้รับการแจ้งเตือนสำหรับวิดีโอใหม่ทุกวิดีโอ</target>
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<target state="translated">วิดีโอของคุณถูกอัปโหลดไปยังบัญชีของคุณและเป็นส่วนตัวแล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="translated">แต่ข้อมูลที่เกี่ยวข้อง (เช่น แท็ก คำอธิบาย) จะไม่ถูกบันทึก คุณแน่ใจว่าต้องการออกจากหน้านี้หรือไม่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="translated">วิดีโอยังไม่ถูกอัปโหลด คุณแน่ใจว่าต้องการออกจากหน้านี้หรือไม่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">อัปโหลด</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="translated">อัปโหลด
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">เผยแพร่วิดีโอแล้ว</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target state="translated">คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ถ้าคุณออกจากหน้านี้ ข้อมูลที่ไม่ได้บันทึกจะหายไป</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">วิดีโอนี้ไม่สามารถรับชมบนเซิร์ฟเวอร์นี้ คุณต้องการเปลี่ยนเส้นทางไปยังเซิร์ฟเวอร์ต้นทางหรือไม่?: <a href="<x id="PH"/>"><x id="PH_1"/></a></target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">การเปลี่ยนเส้นทาง</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="translated">วิดีโอนี้มีเนื้อหาไม่เหมาะสม คุณต้องการรับชมหรือไม่</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="translated">เนื้อหาไม่เหมาะสม</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">รายการถัดไป</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">ยกเลิก</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">การเล่นวิดีโออัตโนมัติถูกหยุด</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="new">Enter/exit fullscreen (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="new">Play/Pause the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="new">Mute/unmute the video (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">ชอบวิดีโอ</target>
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">İzleme geçmişim</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Video sınırı</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="new">Unlimited
<source>Federation</source>
<target state="new">Federation</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="new">followers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702" datatype="html">
<source>Ban this user</source>
<target state="translated">Bu kullanıcıyı yasakla</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Kullanıcı</target>
<source>Username or email address</source>
<target>Kullanıcı adı ya da e-posta adresi</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Şifre</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Şifrenizi sıfırlamak için buraya tıklayın</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Şifremi unuttum</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Hesabınıza giriş yapmak içerik yayınlamanızı sağlar</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Oturum aç</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Ya da şununla oturum aç</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="translated">Şifrenizi mi unuttunuz?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="new">We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">E-posta adresinizi girin, şifrenizi sıfırlamak için bir bağlantı göndereceğiz.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target state="translated">E-posta</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="translated">E-posta adresi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Sıfırla</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">Hesap oluştur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">VİDEOLAR</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit><trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source><target state="new">Import jobs concurrency</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">225</context></context-group></trans-unit><trans-unit id="2184839376696112704" datatype="html">
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Bu bir hata.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="new">Redundancy allowed
<source>Unfollow</source>
<target state="translated">Takipten çık</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="new">Showing
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Kullanıcı adı</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">172</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/users/user-quota.component.html</context><context context-type="linenumber">13</context></context-group></trans-unit><trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source><target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit><trans-unit id="588099657508661970" datatype="html">
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit><trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source><target state="new">None (local authentication)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="translated">Kanallarım</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Bu hesabı ihbar et</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="translated">Kullanıcı adı kopyalandı</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 abone</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> abone</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Yalnızca ses</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Kendiliğinden (ffmpeg ile)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group></trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<target state="translated">Sınır yok</target>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">Sınırsız</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="new">Do you really want to unfollow
<x id="PH"/>?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Takipten çık</target>
<target state="new">You are not following
<x id="PH"/> anymore.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">Hata</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<x id="PH"/> created.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="new">Video channel
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="new">Video channel
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">Hesaba abone olundu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Aboneliklerime git</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Videolarıma git</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Kanallarıma git</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>Klavye Kısayolları:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="translated">Hatalı kullanıcı adı ya da şifre.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Hesabınız engellenmiş.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">herhangi bir dil</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">gizle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">bulanıklaştır</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">göster</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">Bilinmiyor</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">Şifreniz başarıyla sıfırlandı!</target>
<target state="new">Too many attempts, please try again after
<x id="PH"/> minutes.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="translated">Video yayınlandı.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="new">Cancel</target>
<source>Autoplay is suspended</source>
<target state="new">Autoplay is suspended</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Tam ekrana gir/ekrandan çık (oynatıcı odağı gerekli)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Videoyu oynat/durdur (oynatıcı odağı gerekli)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Videonun sesini aç/kapat (oynatıcı odağı gerekli)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="translated">Videoyu beğen</target>
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Моя історія перегляду</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">відео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit><trans-unit id="6438815964972582865" datatype="html">
<source> The following link contains a private token and should not be shared with anyone. </source><target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">19</context></context-group></trans-unit><trans-unit id="187187500641108332" datatype="html">
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">289</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit><trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source><target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit><trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source><target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Квота відео</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="translated">Без обмежень <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> на день)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<source>Federation</source>
<target state="translated">Федерація</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<target state="translated">підписники</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Заблокувати цього користувача</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="new"> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Користувач</target>
<source>Username or email address</source>
<target>Ім'я користувача або email</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Натисніть, щоб скинути ваш пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="new">I forgot my password</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="new"> Logging into an account lets you publish content </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966" datatype="html">
<source>Login</source>
<target state="translated">Увійти за допомогою імені</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Або увійти за допомогою</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<target state="translated">Не пам'ятаю пароль</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Вибачте, але ви не можете відновити пароль, тому що адміністратор вашого сервера не налаштував систему надсилання електронних листів PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="new"> Enter your email address and we will send you a link to reset your password. </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664" datatype="html">
<source>Email</source>
<target state="translated">Email</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<target state="translated">Адреса електронної пошти</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="new">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">Створити обліковий запис</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<source>VIDEOS</source>
<target state="translated">ВІДЕО</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="new">Import jobs concurrency</target>
<source>I'm a teapot</source>
<target state="new">I'm a teapot</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="new">That's an error.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="new">Media is too large for the server. Please contact you administrator if you want to increase the limit size.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">106</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/header/header.component.html</context><context context-type="linenumber">5</context></context-group></trans-unit><trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source><target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="new">Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</target>
<target state="new">ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="new">Follower handle</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group></trans-unit>
+
<trans-unit id="5911214550882917183" datatype="html">
<source>State</source>
<target state="new">State</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="new">Host</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group></trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Надлишковість дозволена <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<source>Unfollow</source>
<target state="new">Unfollow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="new">Open instance in a new tab</target>
<source>No host found matching current filters.</source>
<target state="new">No host found matching current filters.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="new">Your instance is not following anyone.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Показано <x id="INTERPOLATION"/> до <x id="INTERPOLATION_1"/> з <x id="INTERPOLATION_2"/> хостів</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group></trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="new">Follow domains</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group></trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="new">Follow instances</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group></trans-unit><trans-unit id="9216117865911519658" datatype="html">
+
+ <trans-unit id="9216117865911519658" datatype="html">
<source>Action</source><target state="new">Action</target>
<trans-unit id="5248717555542428023" datatype="html">
<source>Username</source>
<target state="new">Username</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="new">e.g. jane_doe</target>
<trans-unit id="4145496584631696119" datatype="html">
<source>Role</source>
<target state="new">Role</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="new">
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="new">None (local authentication)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">23</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-block-list/video-block-list.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group></trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<target state="new">Commented video</target>
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="new">Mute domains</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.html</context><context context-type="linenumber">80</context></context-group></trans-unit><trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source><target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group></trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<target state="new">My Channels</target>
<source>Your message has been sent.</source>
<target state="new">Your message has been sent.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="new">You already sent this form recently</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<target state="translated">Ім'я користувача скопійовано</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 підписник</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> підписники</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group></trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target state="new">Auto (via ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="new">Unlimited</target>
<x id="PH"/> removed from instance followers
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="new">
<x id="PH"/> is not valid
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="new">Follow request(s) sent!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Справді відписатися від <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="new">Unfollow</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Ви більше не стежите за <x id="PH"/>.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="new">enabled</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="new">Error</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target state="new">Update user password</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Користувача <x id="PH"/> онвлено.</target>
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target state="new">Set Email as Verified</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group></trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<target state="new">You cannot ban root.</target>
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">Відеоканал <x id="PH"/> створено.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="new">This name already exists on this instance.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">Відеоканал <x id="PH"/> оновлено.</target>
<source>Banner deleted.</source><target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group></trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="new">Please type the display name of the video channel (
- <x id="PH"/>) to confirm
- </target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">Відеоканал <x id="PH"/> видалено.</target>
<source>Ownership change request sent.</source>
<target state="new">Ownership change request sent.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="new">Subscribe to the account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit><trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source><target state="new">PLAYLISTS</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="new">Go to my subscriptions</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="new">Go to my videos</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="new">Go to my imports</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="new">Go to my channels</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="new">You need to reconnect.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="new">Keyboard Shortcuts:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit><trans-unit id="232050922346936574" datatype="html">
<source>Trending</source><target state="new">Trending</target>
<source>Incorrect username or password.</source>
<target state="new">Incorrect username or password.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="new">Your password has been successfully reset!</target>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target state="translated">Забагато спроб, повторіть спробу через <x id="PH"/> хвилин.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<target state="new">Too many attempts, please try again later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<target state="new">Server error. Please retry later.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<source>Your video was uploaded to your account and is private.</source>
<target state="new">Your video was uploaded to your account and is private.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target state="new">But associated data (tags, description...) will be lost, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target state="new">Your video is not uploaded yet, are you sure you want to leave this page?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="new">Upload</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH"/> </source>
<target state="new">Upload
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<target state="new">Video published.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="new">This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="new">Redirection</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target state="new">This video contains mature or explicit content. Are you sure you want to watch it?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<target state="new">Mature or explicit content</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="new">Up Next</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Скасувати</target>
<source>Autoplay is suspended</source>
<target state="translated">Автовідтворення зупинено</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Вхід/вихід до повноекранного режиму (фокус повинен бути на програвачі)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Відтворення/пауза відео (фокус повинен бути на програвачі)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Увімкнути/вимкнути звук відео (фокус повинен бути на програвачі)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="new">Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="new">Increase the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="new">Decrease the volume (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="new">Seek the video forward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="new">Seek the video backward (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="new">Increase playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="new">Decrease playback rate (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="new">Navigate in the video frame by frame (requires player focus)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184" datatype="html">
<source>Like the video</source>
<target state="new">Like the video</target>
<trans-unit id="187187500641108332" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </source>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action.label }}"/> </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">Lịch sử xem</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>Tạo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">video</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">Đường dẫn chứa một token riêng tư và không nên chia sẻ với bất cứ ai.</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">Bạn đã dùng hết dung lượng cho phép với video này (dung lượng video: <x id="PH" equiv-text="videoSizeBytes"/>, đã dùng: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, dung lượng cho phép: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">Bạn đã dùng hết dung lượng hàng ngày cho phép với video này (dung lượng video: <x id="PH" equiv-text="videoSizeBytes"/>, đã dùng: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, dung lượng cho phép: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">phụ đề</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>Dung lượng</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144" datatype="html">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target state="translated">Không giới hạn <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> mỗi ngày)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">Liên hợp</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>Huỷ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>Chặn người dùng này</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Máy chủ này cho phép đăng ký. Tuy nhiên, hãy cẩn thận đọc kỹ <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Điều khoản dịch vụ<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Điều khoản dịch vụ<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> trước khi tạo tài khoản. Bạn cũng có thể tham khảo thêm một số máy chủ khác tại: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">Máy chủ này đã tắt đăng ký, bạn hãy đọc <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Điều khoản dịch vụ<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> để tìm hiểu thêm hoặc tìm một máy chủ khác cho phép bạn tạo tài khoản và đăng video. Danh sách những máy chủ khác: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>Tài khoản</target>
<source>Username or email address</source>
<target>Tên người dùng hoặc địa chỉ email</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>Mật khẩu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">Click vào đây để reset mật khẩu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">Quên mật khẩu</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">Chỉ có thể đăng video sau khi đăng nhập</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>Đăng nhập</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">Hoặc đăng nhập bằng</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>Quên mật khẩu</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">Rất tiếc, bạn không thể reset mật khẩu bởi vì quản trị viên máy chủ không thiết lập hệ thống email PeerTube.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">Nhập email của bạn và chúng tôi sẽ gửi một đường link reset mật khẩu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>Thư điện tử</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>Địa chỉ thư điện tử</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">Reset</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">trên máy chủ này</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>Tạo tài khoản</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">Video của tôi</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEO</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">Nhập công việc đồng thời</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">Tôi là ấm trà</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">Đây là lỗi.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">Video có dung lượng quá lớn. Hãy liên hệ quản trị viên nếu bạn muốn tăng giới hạn dung lượng.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">TÌM KIẾM TOÀN CẦU</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">Đang tiếp tục tải lên</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">Xin lỗi, tài khoản của bạn đã bị cấm tải lên. Nếu bạn muốn đăng thêm video, bạn phải liên hệ một quản trị viên để mở khóa dung lượng cho phép.</target>
<target>Mã</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
- <target state="translated">Người theo dõi handle</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>Trạng thái</target>
<target state="translated"><x id="INTERPOLATION" equiv-text="{{ action }}"/> </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <target state="translated">Host</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">Đã cho phép dư thừa <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Ngưng theo dõi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">Mở máy chủ trong tab mới</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">Không tìm thấy host trùng khớp với bộ lọc.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">Máy chủ của bạn không theo dõi bất kỳ ai.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">Đang hiện <x id="INTERPOLATION"/> tới <x id="INTERPOLATION_1"/> của <x id="INTERPOLATION_2"/> hosts</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">Theo dõi tên miền</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">Theo dõi những máy chủ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">Hành động</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>Tên đăng nhập</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">e.g. jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>Vai trò</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">Đã bật chuyển đổi độ phân giải. Giới hạn dung lượng chỉ áp dụng vào tài khoản <x id="START_TAG_STRONG"/>gốc<x id="CLOSE_TAG_STRONG"/> thước video. <x id="LINE_BREAK"/> Dù vậy, tài khoản vẫn có thể upload ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">Plugin cho phép</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">Không (xác thực cục bộ)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">Bạn đang ở trên một máy chủ không hỗ trợ HTTPS. Cần phải kích hoạt TLS trước khi theo dõi những máy khác.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">Ẩn máy chủ</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">KÊNH</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239" datatype="html">
<source>This account does not have channels.</source>
<target state="translated">Tài khoản này không mở kênh.</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">Bạn có chắc chắn muốn xóa <x id="PH" equiv-text="videoChannel.displayName"/>? Điều này sẽ xóa hết <x id="PH_1" equiv-text="videoChannel.videosCount"/> video đã đăng trên kênh này, và bạn sẽ không thể tạo kênh khác có cùng tên (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693" datatype="html">
<source>Your message has been sent.</source>
<target state="translated">Tin nhắn của bạn đã được gửi đi.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<target state="translated">Bạn đã gửi rồi gần đây</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">Video tài khoản</target>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH"/> direct account followers </source>
<target state="translated"><x id="PH"/> người theo dõi tài khoản trực tiếp </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">Báo cáo tài khoản này</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">VIDEO</target>
<trans-unit id="25349740244798533" datatype="html">
<source>Username copied</source>
<target state="translated">Đã chép tên tài khoản</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 người đăng ký</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> người đăng ký</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Những máy chủ bạn theo dõi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Những máy chủ đang theo dõi bạn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">Chỉ có âm thanh</target>
<source>Auto (via ffmpeg)</source>
<target state="translated">Tự động (ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">Yêu cầu tên miền.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">Tên miền đã nhập không đúng.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">Những tên miền đã nhập bị trùng lặp.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244" datatype="html">
<source>Unlimited</source>
<target state="translated">Không giới hạn</target>
<source><x id="PH"/> removed from instance followers </source>
<target state="translated"><x id="PH"/> đã bị xóa khỏi người theo dõi máy chủ </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895" datatype="html">
<source><x id="PH"/> is not valid </source>
<target state="translated"><x id="PH"/> vô giá trị </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196" datatype="html">
<source>Follow request(s) sent!</source>
<target state="translated">Đã gửi yêu cầu theo dõi!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target state="translated">Bạn có chắc muốn ngưng theo dõi <x id="PH"/>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">Ngưng theo dõi</target>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH"/> anymore.</source>
<target state="translated">Bạn không còn theo dõi <x id="PH"/> nữa.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
<source>enabled</source>
<target state="translated">đã bật</target>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<target state="translated">Lỗi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">Nhật trình chuẩn</target>
<target state="translated">Đổi mật khẩu người dùng</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">Danh sách đang theo dõi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">Danh sách người theo dõi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">Người dùng <x id="PH"/> đã cập nhật.</target>
<target state="translated">Liên hợp</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">Những máy chủ bạn theo dõi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">Những máy chủ theo dõi bạn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">Video sẽ bị xóa, còn bình luận bị hóa đá.</target>
<target state="translated">Cài Email như Xác Thực</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253" datatype="html">
<source>Video channel <x id="PH"/> created.</source>
<target state="translated">Kênh video <x id="PH"/> đã tạo.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<target state="translated">Tên này đã có người đăng ký.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536" datatype="html">
<source>Video channel <x id="PH"/> updated.</source>
<target state="translated">Kênh video <x id="PH"/> đã cập nhật.</target>
<target state="translated">Đã xóa ảnh bìa.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target state="translated">Hãy nhập tên hiển thị của kênh video ( <x id="PH"/>) để xác nhận</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195" datatype="html">
<source>Video channel <x id="PH"/> deleted.</source>
<target state="translated">Kênh video <x id="PH"/> đã xóa.</target>
<source>Ownership change request sent.</source>
<target state="translated">Đã gửi yêu cầu thay đổi chủ sở hữu.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814" datatype="html">
<source>My channels</source>
<target state="translated">Theo dõi tài khoản này</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">DANH SÁCH PHÁT</target>
<trans-unit id="3779524668013120370" datatype="html">
<source>Go to my subscriptions</source>
<target state="translated">Đến lượt đăng ký của tôi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<target state="translated">Đến trang video của tôi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<target state="translated">Đến trang video tôi nhập</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<target state="translated">Đến kênh của tôi</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">Không thể truy xuất thông tin đăng nhập ứng dụng khách OAuth: <x id="PH"/>. Hãy chắc rằng bạn đã cấu hình đúng PeerTube (config/ directory), đặc biệt là phần "webserver".</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544" datatype="html">
<source>You need to reconnect.</source>
<target state="translated">Bạn cần kết nối lại.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<source>Keyboard Shortcuts:</source>
<target state="translated">Phím tắt:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246" datatype="html">
<source>Incorrect username or password.</source>
<target state="translated">Sai tên hoặc mật khẩu.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">Tài khoản của bạn đã bị khóa.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">ngôn ngữ bất kỳ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">ẩn</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">làm mờ</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">hiển thị</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">—</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853" datatype="html">
<source>Your password has been successfully reset!</source>
<target state="translated">Bạn đã đổi mật khẩu thành công!</target>
<target>Bạn đã thực hiện điều này quá nhiều lần, xin thử lại sau
<x id="PH"/> phút.
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>Quá nhiều lần thực hiện, vui lòng thử lại sau.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>Lỗi máy chủ. Xin thử lại sau.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">Đã đăng toàn bộ kênh gần đây của <x id="PH"/>. Bạn sẽ nhận được thông báo về video mới của họ.</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>Video đã được tải lên riêng tư vào tài khoản của bạn.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>Nhưng các dữ liệu liên quan (thẻ, mô tả,...) sẽ bị mất. Bạn có chắc muốn rời khỏi trang không?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>Video của bạn vẫn chưa được tải lên, bạn có chắc muốn rời trang?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">Tải lên</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>Tải lên
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>Đã xuất bản video.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>Bạn có sửa đổi chưa lưu! Nếu rời đi, những sửa đổi này sẽ bị mất.</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">Video không khả dụng trên máy chủ này. Bạn có muốn chuyển tới máy chủ gốc: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">Chuyển hướng</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>Video này chứa nội dung cho người lớn hoặc nhạy cảm. Bạn có chắc chắn muốn xem không?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>Nội dung người lớn hoặc nhạy cảm</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">Tiếp Theo</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">Hủy bỏ</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">Tạm ngừng tự phát</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">Mở/thoát toàn màn hình (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">Phát/Ngừng video (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">Ẩn/bỏ ẩn video (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">Chuyển đến một mức phần trăm của video: 0 là 0% và 9 là 90% (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">Tăng âm lượng (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">Giảm âm lượng (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">Tua tới video (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">Tua lùi video (yêu cầu trọng tâm video)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">Tăng tốc độ phát (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">Giảm tốc độ phát (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">Điều hướng trong từng khung hình video (yêu cầu trọng tâm trình phát)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>Thích video</target>
<context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context>
<context context-type="linenumber">48</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">33</context>
+ </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">117</context>
+ <context context-type="linenumber">121</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">408</context>
+ <context context-type="linenumber">415</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/modal/confirm.component.html</context>
<source>Your message has been sent.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context>
- <context context-type="linenumber">89</context>
+ <context context-type="linenumber">88</context>
</context-group>
</trans-unit>
<trans-unit id="2072135752262464360" datatype="html">
<source>You already sent this form recently</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context>
- <context context-type="linenumber">95</context>
+ <context context-type="linenumber">94</context>
</context-group>
</trans-unit>
<trans-unit id="1045244999981860085" datatype="html">
<source>CHANNELS</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
+ <context context-type="linenumber">81</context>
</context-group>
</trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">83</context>
+ <context context-type="linenumber">82</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context>
<source>Username copied</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">121</context>
+ <context context-type="linenumber">120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context>
<source>1 subscriber</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">125</context>
+ <context context-type="linenumber">124</context>
</context-group>
</trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH" equiv-text="count"/> subscribers</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">127</context>
+ <context context-type="linenumber">126</context>
</context-group>
</trans-unit>
<trans-unit id="4856575356061361269" datatype="html">
<source><x id="PH" equiv-text="account.followersCount"/> direct account followers</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">155</context>
+ <context context-type="linenumber">154</context>
</context-group>
</trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">196</context>
+ <context context-type="linenumber">195</context>
</context-group>
</trans-unit>
<trans-unit id="8564701209009684429" datatype="html">
<context context-type="linenumber">58</context>
</context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
+ <trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
<context context-type="linenumber">29</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">3</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
</context-group>
</trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
+ <trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
- <context context-type="linenumber">3</context>
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
</context-group>
</trans-unit>
<trans-unit id="9031514421077169181" datatype="html">
<context context-type="linenumber">50</context>
</context-group>
</trans-unit>
+ <trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2845798909207198924" datatype="html">
<source>Showing <x id="INTERPOLATION" equiv-text="{{'{first}'}}"/> to <x id="INTERPOLATION_1" equiv-text="{{'{last}'}}"/> of <x id="INTERPOLATION_2" equiv-text="{{'{totalRecords}'}}"/> followers</source>
<context-group purpose="location">
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
- <trans-unit id="2265605798180116441" datatype="html">
- <source>Follower handle</source>
+ <trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
<context context-type="linenumber">24</context>
<context context-type="linenumber">81</context>
</context-group>
</trans-unit>
- <trans-unit id="4774348799569692380" datatype="html">
- <source>Showing <x id="INTERPOLATION" equiv-text="{{'{first}'}}"/> to <x id="INTERPOLATION_1" equiv-text="{{'{last}'}}"/> of <x id="INTERPOLATION_2" equiv-text="{{'{totalRecords}'}}"/> hosts</source>
+ <trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
</trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
+ <trans-unit id="4917252294930256268" datatype="html">
+ <source> It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers. </source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">28,29</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="2355066641781598196" datatype="html">
+ <source>Follow request(s) sent!</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context>
+ <context context-type="linenumber">62</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">18</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="4774348799569692380" datatype="html">
+ <source>Showing <x id="INTERPOLATION" equiv-text="{{'{first}'}}"/> to <x id="INTERPOLATION_1" equiv-text="{{'{last}'}}"/> of <x id="INTERPOLATION_2" equiv-text="{{'{totalRecords}'}}"/> hosts</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">11</context>
</context-group>
</trans-unit>
<trans-unit id="9216117865911519658" datatype="html">
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
- <trans-unit id="6641024648411549335" datatype="html">
- <source>Host</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">31</context>
- </context-group>
- </trans-unit>
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON" ctype="x-p_sorticon" equiv-text="<p-sortIcon field="redundancyAllowed">"/><x id="CLOSE_TAG_P_SORTICON" ctype="x-p_sorticon" equiv-text="</p-sortIcon>"/></source>
<context-group purpose="location">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context>
- <context context-type="linenumber">58</context>
+ <context context-type="linenumber">48</context>
</context-group>
</trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>No host found matching current filters.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">70</context>
+ <context context-type="linenumber">71</context>
</context-group>
</trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">71</context>
- </context-group>
- </trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">78</context>
- </context-group>
- </trans-unit>
- <trans-unit id="4917252294930256268" datatype="html">
- <source> It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers. </source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
- <context context-type="linenumber">81,82</context>
- </context-group>
- </trans-unit>
- <trans-unit id="2355066641781598196" datatype="html">
- <source>Follow request(s) sent!</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context>
- <context context-type="linenumber">47</context>
+ <context context-type="linenumber">72</context>
</context-group>
</trans-unit>
<trans-unit id="4245720728052819482" datatype="html">
<source>Do you really want to unfollow <x id="PH" equiv-text="follow.following.host"/>?</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context>
- <context context-type="linenumber">57</context>
+ <context context-type="linenumber">47</context>
</context-group>
</trans-unit>
<trans-unit id="3935234189109112926" datatype="html">
<source>You are not following <x id="PH" equiv-text="follow.following.host"/> 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">64</context>
- </context-group>
- </trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
- <context context-type="linenumber">28</context>
- </context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
- <context context-type="linenumber">37</context>
+ <context context-type="linenumber">54</context>
</context-group>
</trans-unit>
<trans-unit id="2593763089859685916" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context>
- <context context-type="linenumber">103</context>
+ <context context-type="linenumber">102</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context>
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
<context context-type="linenumber">83</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">111</context>
+ </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context>
<context context-type="linenumber">6</context>
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
<context context-type="linenumber">105</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">112</context>
+ </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">107</context>
+ <context context-type="linenumber">111</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">34</context>
+ <context context-type="linenumber">38</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">36</context>
+ <context context-type="linenumber">40</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context>
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
<context context-type="linenumber">136</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">114</context>
+ </context-group>
</trans-unit>
<trans-unit id="2602586221576511475" datatype="html">
<source>Video quota</source>
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
<context context-type="linenumber">151</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">113</context>
+ </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context>
<context context-type="linenumber">47</context>
<context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
<context context-type="linenumber">188</context>
</context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">121</context>
+ </context-group>
</trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<context context-type="linenumber">281</context>
</context-group>
</trans-unit>
+ <trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="3403978719736970622" datatype="html">
<source>You cannot ban root.</source>
<context-group purpose="location">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">44</context>
+ <context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.html</context>
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
+ <trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
+ <context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
+ <context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="2308975396733519902" datatype="html">
<source>Create an account</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">50</context>
+ <context context-type="linenumber">54</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.html</context>
<source> Logging into an account lets you publish content </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
+ <context context-type="linenumber">60,61</context>
</context-group>
</trans-unit>
<trans-unit id="7252854992688790751" datatype="html">
<source> This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
+ <context context-type="linenumber">64,66</context>
</context-group>
</trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source> Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
+ <context context-type="linenumber">69,71</context>
</context-group>
</trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">72</context>
+ <context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit id="3238209155172574367" datatype="html">
<source>Forgot your password</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">91</context>
+ <context context-type="linenumber">95</context>
</context-group>
</trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source> We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system. </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">99,100</context>
+ <context context-type="linenumber">103,104</context>
</context-group>
</trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source> Enter your email address and we will send you a link to reset your password. </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">103,104</context>
+ <context context-type="linenumber">107,108</context>
</context-group>
</trans-unit>
<trans-unit id="3967269098753656610" datatype="html">
<source>Email address</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">109</context>
+ <context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context>
<source>Reset</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">122</context>
+ <context context-type="linenumber">126</context>
</context-group>
<note priority="1" from="description">Password reset button</note>
</trans-unit>
<source>Incorrect username or password.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.ts</context>
- <context context-type="linenumber">159</context>
+ <context context-type="linenumber">163</context>
</context-group>
</trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+login/login.component.ts</context>
- <context context-type="linenumber">160</context>
+ <context context-type="linenumber">164</context>
</context-group>
</trans-unit>
<trans-unit id="6658000829978978023" datatype="html">
<source>Video channel <x id="PH" equiv-text="videoChannelCreate.displayName"/> created.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context>
- <context context-type="linenumber">67</context>
+ <context context-type="linenumber">66</context>
</context-group>
</trans-unit>
<trans-unit id="8723777130353305761" datatype="html">
<source>This name already exists on this instance.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context>
- <context context-type="linenumber">73</context>
+ <context context-type="linenumber">72</context>
</context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<context context-type="linenumber">44,46</context>
</context-group>
</trans-unit>
- <trans-unit id="2575302837003821736" datatype="html">
- <source>Please type the display name of the video channel (<x id="PH" equiv-text="videoChannel.displayName"/>) to confirm</source>
+ <trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">64</context>
</context-group>
</trans-unit>
+ <trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="1788875035518441092" datatype="html">
<source>Last published first</source>
<context-group purpose="location">
<source>I'm a teapot</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context>
- <context context-type="linenumber">26</context>
+ <context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="3851357780293085233" datatype="html">
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">704</context>
+ <context context-type="linenumber">711</context>
</context-group>
</trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>Upload on hold</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">124</context>
+ <context context-type="linenumber">123</context>
</context-group>
</trans-unit>
<trans-unit id="3284171506518522275" datatype="html">
<source>Your video was uploaded to your account and is private.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">162</context>
+ <context context-type="linenumber">161</context>
</context-group>
</trans-unit>
<trans-unit id="5699822024600815733" datatype="html">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">163</context>
+ <context context-type="linenumber">162</context>
</context-group>
</trans-unit>
<trans-unit id="1219739004043110649" datatype="html">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">165</context>
+ <context context-type="linenumber">164</context>
</context-group>
</trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">222</context>
+ <context context-type="linenumber">221</context>
</context-group>
</trans-unit>
<trans-unit id="8278735427925094503" datatype="html">
<source>Upload <x id="PH" equiv-text="videofile.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">224</context>
+ <context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="5981816353437801748" datatype="html">
<source>Video published.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">245</context>
+ <context context-type="linenumber">244</context>
</context-group>
</trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">288</context>
+ <context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context>
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">323</context>
+ <context context-type="linenumber">322</context>
</context-group>
</trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context>
- <context context-type="linenumber">341</context>
+ <context context-type="linenumber">340</context>
</context-group>
</trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context>
<context context-type="linenumber">24</context>
</context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context>
- <context context-type="linenumber">3</context>
- </context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context>
<context context-type="linenumber">27</context>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH" equiv-text="originUrl"/>"><x id="PH_1" equiv-text="originUrl"/></a>?</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">288</context>
+ <context context-type="linenumber">295</context>
</context-group>
</trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">289</context>
+ <context context-type="linenumber">296</context>
</context-group>
</trans-unit>
<trans-unit id="8858527736400081688" datatype="html">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">335</context>
+ <context context-type="linenumber">342</context>
</context-group>
</trans-unit>
<trans-unit id="3937119019020041049" datatype="html">
<source>Mature or explicit content</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">336</context>
+ <context context-type="linenumber">343</context>
</context-group>
</trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">407</context>
+ <context context-type="linenumber">414</context>
</context-group>
</trans-unit>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">409</context>
+ <context context-type="linenumber">416</context>
</context-group>
</trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">678</context>
+ <context context-type="linenumber">685</context>
</context-group>
</trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">679</context>
+ <context context-type="linenumber">686</context>
</context-group>
</trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">680</context>
+ <context context-type="linenumber">687</context>
</context-group>
</trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">682</context>
+ <context context-type="linenumber">689</context>
</context-group>
</trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">684</context>
+ <context context-type="linenumber">691</context>
</context-group>
</trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">685</context>
+ <context context-type="linenumber">692</context>
</context-group>
</trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">687</context>
+ <context context-type="linenumber">694</context>
</context-group>
</trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">688</context>
+ <context context-type="linenumber">695</context>
</context-group>
</trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">690</context>
+ <context context-type="linenumber">697</context>
</context-group>
</trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">691</context>
+ <context context-type="linenumber">698</context>
</context-group>
</trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context>
- <context context-type="linenumber">693</context>
+ <context context-type="linenumber">700</context>
</context-group>
</trans-unit>
<trans-unit id="7627544798203088407" datatype="html">
<source>Go to my subscriptions</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">64</context>
+ <context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="1136469849928650779" datatype="html">
<source>Go to my videos</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">68</context>
+ <context context-type="linenumber">67</context>
</context-group>
</trans-unit>
<trans-unit id="7836683738999600376" datatype="html">
<source>Go to my imports</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">72</context>
+ <context context-type="linenumber">71</context>
</context-group>
</trans-unit>
<trans-unit id="7511292153332773503" datatype="html">
<source>Go to my channels</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">76</context>
+ <context context-type="linenumber">75</context>
</context-group>
</trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">99,100</context>
+ <context context-type="linenumber">98,99</context>
</context-group>
</trans-unit>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">104</context>
+ <context context-type="linenumber">103</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context>
<source>You need to reconnect.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/auth/auth.service.ts</context>
- <context context-type="linenumber">220</context>
+ <context context-type="linenumber">219</context>
</context-group>
</trans-unit>
<trans-unit id="2206638022166154361" datatype="html">
<context context-type="linenumber">98</context>
</context-group>
</trans-unit>
+ <trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="2821179408673282599" datatype="html">
<source>Home</source>
<context-group purpose="location">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context>
- <context context-type="linenumber">62</context>
+ <context context-type="linenumber">61</context>
</context-group>
</trans-unit>
<trans-unit id="968295009933361070" datatype="html">
<source>Too many attempts, please try again after <x id="PH" equiv-text="minutesLeft"/> minutes.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context>
- <context context-type="linenumber">67</context>
+ <context context-type="linenumber">66</context>
</context-group>
</trans-unit>
<trans-unit id="4965472196059235310" datatype="html">
<source>Too many attempts, please try again later.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context>
- <context context-type="linenumber">69</context>
+ <context context-type="linenumber">68</context>
</context-group>
</trans-unit>
<trans-unit id="1693549688987384699" datatype="html">
<source>Server error. Please retry later.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context>
- <context context-type="linenumber">72</context>
+ <context context-type="linenumber">71</context>
</context-group>
</trans-unit>
<trans-unit id="4670312387769733978" datatype="html">
<source>Unknown</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.ts</context>
- <context context-type="linenumber">193</context>
+ <context context-type="linenumber">196</context>
</context-group>
</trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.ts</context>
- <context context-type="linenumber">263</context>
+ <context context-type="linenumber">266</context>
</context-group>
</trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.ts</context>
- <context context-type="linenumber">298</context>
+ <context context-type="linenumber">301</context>
</context-group>
</trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.ts</context>
- <context context-type="linenumber">302</context>
+ <context context-type="linenumber">305</context>
</context-group>
</trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/menu/menu.component.ts</context>
- <context context-type="linenumber">306</context>
+ <context context-type="linenumber">309</context>
</context-group>
</trans-unit>
<trans-unit id="403762424689874454" datatype="html">
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
- <trans-unit id="2740793005745065895" datatype="html">
- <source><x id="PH" equiv-text="host"/> is not valid</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context>
- <context context-type="linenumber">19</context>
- </context-group>
- </trans-unit>
- <trans-unit id="2127446333083057097" datatype="html">
- <source>Domain is required.</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context>
- <context context-type="linenumber">56</context>
- </context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context>
- <context context-type="linenumber">57</context>
- </context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context>
- <context context-type="linenumber">58</context>
- </context-group>
- </trans-unit>
<trans-unit id="7784486624424057376" datatype="html">
<source>Instance name is required.</source>
<context-group purpose="location">
<context context-type="linenumber">119</context>
</context-group>
</trans-unit>
+ <trans-unit id="2740793005745065895" datatype="html">
+ <source><x id="PH" equiv-text="host"/> is not valid</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">27</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">50</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="2127446333083057097" datatype="html">
+ <source>Domain is required.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">92</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">101</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
+ </trans-unit>
<trans-unit id="8602814243662345124" datatype="html">
<source>Email is required.</source>
<context-group purpose="location">
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">我的历史记录</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>创建</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">视频</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="new"> The following link contains a private token and should not be shared with anyone. </target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="new">Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="new">Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">字幕</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>视频存储空间</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>无限制 <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> 每日)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target state="translated">联盟</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106" datatype="html">
<source>followers</source>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>封禁此用户</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">此实例允许注册。但是,请小心检查 <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>条款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>条款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 你也可以通过以下链接搜寻其他服务,以配合你的实际需要: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">目前此实例不允许用户注册,您可以检查 <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>条款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 以了解详情,或寻找别的站台,好让您注册帐号并上传您的视频。看看一众站台中有哪个合您心意: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>用户</target>
<source>Username or email address</source>
<target>用户名或电子邮件地址</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>密码</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">点击此处重置您的密码</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">我忘记了我 密码</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">登录帐户就可以让您发布内容</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>登录</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">或使用其他账户登入</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>忘记密码</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488" datatype="html">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target state="translated">对不起,您无法恢复您的密码,因为您的实例管理员没有配置 PeerTube 电子邮件系统。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">输入您的电子邮件地址,我们将发送一个链接,以重置您的密码。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>电子邮件地址</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>电子邮件地址</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">重设</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">在此网站</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>创建帐户</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">我的视频</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">视频</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">导入并发送</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">我是茶壶</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">发生错误.</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">媒体对于服务器太大。如果您想增加限制大小,请与管理员联系。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="new">Upload on hold</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">对不起,您的帐户的上传功能已被禁用。如果你想添加视频,管理员必须解锁您的权限。</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>管理关注</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>状态</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>主机名</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">允许冗余 <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">取消关注</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">在新选项卡中打开页面</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">没有找到匹配当前筛选器的主机。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">您的站点没有跟踪任何人。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">正在观看 <x id="INTERPOLATION"/> 到 <x id="INTERPOLATION_1"/> 总共有 <x id="INTERPOLATION_2"/> 个主机</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">关注域名</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">跟踪站点</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="new">Action</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>用户名</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">例如: jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>角色</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">已启用转码。视频配额仅考虑在内 <x id="START_TAG_STRONG"/>原始<x id="CLOSE_TAG_STRONG"/> 视频大小。 <x id="LINE_BREAK"/> 这个用户最多可以上传 ~ <x id="INTERPOLATION"/>. </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="new">Auth plugin</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">None (本地身份验证)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">看起来你不在 HTTPS 服务器上。你的网络服务器需要有 TLS 激活,以便跟踪服务器。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">静音网络</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="new">CHANNELS</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>此帐户没有视频频道。</target>
It will delete <x id="PH_1"/> videos uploaded in this channel, and you will not be able to create another
channel with the same name (<x id="PH_2"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<source>Your message has been sent.</source>
<target>您的信息已发送。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>您最近已发送了此表格</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="new">Account videos</target>
<target state="new">
<x id="PH"/> direct account followers
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="new">Report this account</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="new">VIDEOS</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>用户名已复制</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="new">1 subscriber</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="new"><x id="PH"/> subscribers</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="new">Audio-only</target>
<source>Auto (via ffmpeg)</source>
<target>自动(由 ffmpeg 决定)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="new">Domain is required.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="new">Domains entered are invalid.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="new">Domains entered contain duplicates.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>无限制
<x id="PH"/> 已被移除出关注列表
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> 不合法
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>关注请求已发送!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>您确定要取消关注
<x id="PH"/> 吗?
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>取消关注</target>
<target>您已不再关注
<x id="PH"/>。
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>已启用</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>错误</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="new">Standard logs</target>
<target>更改用户密码</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="new">Following list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="new">Followers list</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="new">User
<target state="new">Federation</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="new">Instances you follow</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="new">Instances following you</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="new">Videos will be deleted, comments will be tombstoned.</target>
<target>把电子邮件地址设为已验证</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<target>视频频道
<x id="PH"/> 已创建。
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>此用户名在本实例上已经被使用过。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>视频频道
<target state="new">Banner deleted.</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>输入视频频道的显示名(
- <x id="PH"/>)以确认操作
- </target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>视频频道
<source>Ownership change request sent.</source>
<target>视频转移请求已发送。</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>订阅此帐户</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">播放列表</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>转到我的订阅</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>转到我的视频</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>转到我的导入</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>转到我的频道</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="new">Cannot retrieve OAuth Client credentials: <x id="PH"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>请重新进行授权。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>键盘快捷键:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>用户名或密码不正确。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="new">Your account is blocked.</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="new">any language</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="new">hide</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="new">blur</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="new">display</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="new">Unknown</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>密码重置成功!</target>
<target>尝试次数过多,请在
<x id="PH"/> 分钟后重试。
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>尝试次数过多,请稍后重试。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>服务器出现错误。请稍后重试。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="new">Subscribed to all current channels of
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>您的视频已经以私有方式上传至您的帐户。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>相关信息(如标签、说明)将会丢失,您确定要离开这个页面吗?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>您的视频尚未上传完毕,您确定要离开这个页面吗?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">上传</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>上传
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>视频已发布。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>您有未保存的修改!如果您离开本页面,您将会失去这些修改。</target>
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">此视频在此实例上不可用,是否要在原始实例上重定向: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">重新导向</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>此视频包含成人或裸露内容。您确定要观看吗?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>成人或裸露内容</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">往下</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">取消</target>
<source>Autoplay is suspended</source>
<target state="translated">自动播放已经暂停</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">进入/离开全屏幕(需要播放器聚焦)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">播放/暂停视频(需要播放器聚焦)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">静音/解除视频静音(需要播放器焦点)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">跳到视频的百分比:0 是 0%,9 是 90%(需要播放器焦点)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">增加音量(需要播放器焦点)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">降低音量(需要播放器焦点)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">快进视频(需要播放器焦点)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">向后快退视频(需要播放器焦点點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">提高播放速度(需要播放器点击)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">减慢播放速度(需要播放器点击)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">逐画格浏览视频(需要点击播放器)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target state="translated">喜欢这视频</target>
<target state="translated">
<x id="INTERPOLATION" equiv-text="{{ action.label }}"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.html</context><context context-type="linenumber">77</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/buttons/action-dropdown.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">14</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-main/misc/top-menu-dropdown.component.html</context><context context-type="linenumber">24</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">52</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">78</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">101</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/videos-selection.component.html</context><context context-type="linenumber">1</context></context-group></trans-unit>
<trans-unit id="1486537403020619891" datatype="html">
<source>My watch history</source>
<target state="translated">我的觀看紀錄</target>
<trans-unit id="5674286808255988565">
<source>Create</source>
<target>建立</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">103</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">102</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts</context><context context-type="linenumber">89</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-video-playlists/my-video-playlist-edit.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-playlist/video-add-to-playlist.component.html</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="1006562256968398209" datatype="html">
<source>video</source>
<target state="translated">影片</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">288</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">287</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.ts</context><context context-type="linenumber">55</context></context-group></trans-unit>
<trans-unit id="6438815964972582865" datatype="html">
<source>The following link contains a private token and should not be shared with anyone.</source>
<target state="translated">以下連結包含了一個專用權杖,不應該與其他人分享。</target>
<trans-unit id="6995024616159044376" datatype="html">
<source>Your video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="videoQuotaUsedBytes"/>, quota: <x id="PH_2" equiv-text="videoQuotaBytes"/>)</source>
<target state="translated">此影片超過了您的影片配額(影片大小:<x id="PH" equiv-text="videoSizeBytes"/>,已使用:<x id="PH_1" equiv-text="videoQuotaUsedBytes"/>,配額:<x id="PH_2" equiv-text="videoQuotaBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">323</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">322</context></context-group></trans-unit>
<trans-unit id="7873395933409147217" datatype="html">
<source>Your daily video quota is exceeded with this video (video size: <x id="PH" equiv-text="videoSizeBytes"/>, used: <x id="PH_1" equiv-text="quotaUsedDailyBytes"/>, quota: <x id="PH_2" equiv-text="quotaDailyBytes"/>)</source>
<target state="translated">此影片超過了您的每日影片配額(影片大小:<x id="PH" equiv-text="videoSizeBytes"/>,已使用:<x id="PH_1" equiv-text="quotaUsedDailyBytes"/>,配額:<x id="PH_2" equiv-text="quotaDailyBytes"/>)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">341</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">340</context></context-group></trans-unit>
<trans-unit id="5235042777215655908" datatype="html">
<source>subtitles</source>
<target state="translated">字幕</target>
<trans-unit id="2602586221576511475">
<source>Video quota</source>
<target>影片配額</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">151</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-features-table.component.html</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="1502595455339510144">
<source>Unlimited <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/> per day)<x id="CLOSE_TAG_NG_CONTAINER"/></source>
<target>無限 <x id="START_TAG_NG_CONTAINER"/>(<x id="INTERPOLATION"/>每日)<x id="CLOSE_TAG_NG_CONTAINER"/></target>
<target>聯盟</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-instance/instance-statistics.component.html</context><context context-type="linenumber">58</context></context-group>
+ </trans-unit><trans-unit id="8726138323871139597" datatype="html">
+ <source>Following</source><target state="new">Following</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">29</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">31</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">28</context>
+ </context-group>
+ </trans-unit><trans-unit id="4914577418256256836" datatype="html">
+ <source>Followers</source><target state="new">Followers</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/admin.component.ts</context>
+ <context context-type="linenumber">34</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
</trans-unit>
<trans-unit id="3541687134897970106">
<source>followers</source>
<trans-unit id="2159130950882492111">
<source>Cancel</source>
<target>取消</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">408</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">33</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">121</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.html</context><context context-type="linenumber">22</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html</context><context context-type="linenumber">37</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">69</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.html</context><context context-type="linenumber">81</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/shared/comment/video-comment-add.component.html</context><context context-type="linenumber">73</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">415</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/modal/confirm.component.html</context><context context-type="linenumber">20</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/moderation-comment-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">31</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/report.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/report-modals/video-report.component.html</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-ban-modal.component.html</context><context context-type="linenumber">26</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/video-block.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-video-miniature/video-download.component.html</context><context context-type="linenumber">152</context></context-group></trans-unit>
<trans-unit id="3616223838716839702">
<source>Ban this user</source>
<target>阻擋此使用者</target>
<trans-unit id="7252854992688790751" datatype="html">
<source>This instance allows registration. However, be careful to check the <x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> before creating an account. You may also search for another instance to match your exact needs at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">此站臺允許註冊。然而,請留心查閱<x id="START_LINK" ctype="x-a" equiv-text="<a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>"/>條款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/><x id="START_LINK_1" equiv-text="<a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">"/>條款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> ,然後才建立帳號。您亦可搜尋另一個站臺以切合您的需要:<x id="LINE_BREAK" ctype="lb" equiv-text="<br />"/><x id="START_LINK_2" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。 </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">60,62</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">64</context></context-group></trans-unit>
<trans-unit id="7215649348148521605" datatype="html">
<source>Currently this instance doesn't allow for user registration, you may check the <x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>Terms<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there. Find yours among multiple instances at: <x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. </source>
<target state="translated">目前此站臺不允許使用者註冊,您可查閱<x id="START_LINK" ctype="x-a" equiv-text="<a (click)="onTermsClick($event, instanceInformation)" href='#'>"/>條款<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 以瞭解詳情,或尋找別的站臺,好讓您註冊帳號並上載您的影片。看看一眾站臺中有哪個合您心意:<x id="LINE_BREAK" ctype="lb" equiv-text="<br /> "/><x id="START_LINK_1" equiv-text="<a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">"/>https://joinpeertube.org/instances<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。 </target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">65,67</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">69</context></context-group></trans-unit>
<trans-unit id="2392488717875840729">
<source>User</source>
<target>使用者</target>
<source>Username or email address</source>
<target>使用者名稱或電子信箱</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">23</context></context-group>
+ </trans-unit><trans-unit id="1758058452376026925" datatype="html">
+ <source> ⚠️ Most email addresses do not include capital letters. </source><target state="new"> ⚠️ Most email addresses do not include capital letters. </target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+login/login.component.html</context>
+ <context context-type="linenumber">33,34</context>
+ </context-group>
</trans-unit>
<trans-unit id="1431416938026210429">
<source>Password</source>
<target>密碼</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">36</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">117</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">38</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">40</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">8</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+reset-password/reset-password.component.html</context><context context-type="linenumber">10</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">56</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">58</context></context-group></trans-unit>
<trans-unit id="8715156686857791956" datatype="html">
<source>Click here to reset your password</source>
<target state="translated">點擊此處以重設您的密碼</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">47</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="892063502898494584" datatype="html">
<source>I forgot my password</source>
<target state="translated">我忘了我的密碼</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">47</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">51</context></context-group></trans-unit>
<trans-unit id="2101170466365500913" datatype="html">
<source>Logging into an account lets you publish content</source>
<target state="translated">登入帳號就可讓您發佈內容</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+login/login.component.html</context>
- <context context-type="linenumber">56,57</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">60</context></context-group></trans-unit>
<trans-unit id="2454050363478003966">
<source>Login</source>
<target>登入</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">44</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login-routing.module.ts</context><context context-type="linenumber">12</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">48</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">99</context></context-group></trans-unit>
<trans-unit id="3183213940445113677" datatype="html">
<source>Or sign in with</source>
<target state="translated">或使用其他帳戶登入</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="3238209155172574367">
<source>Forgot your password</source>
<target>忘記您的密碼</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">91</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">95</context></context-group></trans-unit>
<trans-unit id="87327320394367488">
<source>We are sorry, you cannot recover your password because your instance administrator did not configure the PeerTube email system.</source>
<target>我們很抱歉,您無法復原您的密碼,因為您的站臺管理員並未設定 PeerTube 電子郵件系統。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="3188014010833256853" datatype="html">
<source>Enter your email address and we will send you a link to reset your password.</source>
<target state="translated">輸入您的電子郵件地址,然後我們將會寄送連結給您重設您的密碼。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group></trans-unit>
<trans-unit id="1190256911880544559" datatype="html">
<source>An email with the reset password instructions will be sent to <x id="PH" equiv-text="this.forgotPasswordEmail"/>.
The link will expire within 1 hour.</source>
<trans-unit id="4768749765465246664">
<source>Email</source>
<target>電子郵件</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">107</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group>
- </trans-unit>
+
+
+
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">105</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">112</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html</context><context context-type="linenumber">4</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">45</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">47</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">8</context></context-group></trans-unit>
<trans-unit id="3967269098753656610">
<source>Email address</source>
<target>電子信箱</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">109</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">113</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html</context><context context-type="linenumber">10</context></context-group></trans-unit>
<trans-unit id="7808756054397155068" datatype="html">
<source>Reset</source>
<target state="translated">重設</target>
<note priority="1" from="description">Password reset button</note>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">122</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">126</context></context-group></trans-unit>
<trans-unit id="4319634264526091601" datatype="html">
<source>on this instance</source>
<target state="translated">在此站臺</target>
<trans-unit id="2308975396733519902">
<source>Create an account</source>
<target>建立帳號</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">50</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.html</context><context context-type="linenumber">54</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.html</context><context context-type="linenumber">100</context></context-group></trans-unit>
<trans-unit id="3058024914967508975" datatype="html">
<source>My videos</source>
<target state="translated">我的影片</target>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">影片</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">82</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html</context><context context-type="linenumber">215</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
<trans-unit id="667372110624203230" datatype="html">
<source>Import jobs concurrency</source>
<target state="translated">匯入工作並行</target>
<trans-unit id="4424964105331349857" datatype="html">
<source>I'm a teapot</source>
<target state="translated">我是茶壺</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">26</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+page-not-found/page-not-found.component.ts</context><context context-type="linenumber">27</context></context-group></trans-unit>
<trans-unit id="1597262876035959248" datatype="html">
<source>That's an error.</source>
<target state="translated">發生錯誤。</target>
<trans-unit id="2971365540217107489" datatype="html">
<source>Media is too large for the server. Please contact you administrator if you want to increase the limit size.</source>
<target state="translated">媒體對此伺服器來說太大。如果您想要增加限制大小的話,請聯絡您的管理員。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">62</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">61</context></context-group></trans-unit>
<trans-unit id="5131854469652959713" datatype="html">
<source>GLOBAL SEARCH</source>
<target state="translated">全域搜尋</target>
<trans-unit id="9172233176401579786">
<source>Scheduled</source>
<target>排定</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">192</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">192</context></context-group>
+ </trans-unit>
<trans-unit id="1435317307066082710" datatype="html">
<source>Hide the video until a specific date</source>
<target state="translated">在特定日期前隱藏影片</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">193</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/shared/video-edit.component.ts</context><context context-type="linenumber">193</context></context-group>
+ </trans-unit>
<trans-unit id="6148369758871787018">
<source>Video background image</source>
<target>影片背景圖片</target>
<trans-unit id="6161604372916832458" datatype="html">
<source>Upload on hold</source>
<target state="translated">暫緩上傳</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">124</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">123</context></context-group></trans-unit>
<trans-unit id="285180972645018518" datatype="html">
<source>Sorry, the upload feature is disabled for your account. If you want to add videos, an admin must unlock your quota.</source>
<target state="translated">抱歉,您的帳號已停用上傳功能。如果您想要新增影片,管理員必須解鎖您的配額。</target>
<target>ID</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/system/jobs/jobs.component.html</context><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="2265605798180116441">
- <source>Follower handle</source>
- <target>追蹤者處理</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">24</context></context-group>
- </trans-unit>
+
<trans-unit id="5911214550882917183">
<source>State</source>
<target>狀態</target>
</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/batch-domains-modal.component.html</context><context context-type="linenumber">3</context></context-group>
</trans-unit>
- <trans-unit id="6641024648411549335">
- <source>Host</source>
- <target>主機</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">31</context></context-group>
- </trans-unit>
+
<trans-unit id="6571718060636962350" datatype="html">
<source>Redundancy allowed <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></source>
<target state="translated">允許冗餘 <x id="START_TAG_P_SORTICON"/><x id="CLOSE_TAG_P_SORTICON"/></target>
<trans-unit id="9160510009013134726" datatype="html">
<source>Unfollow</source>
<target state="translated">取消追蹤</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">58</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">41</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">48</context></context-group></trans-unit>
<trans-unit id="8246779176913476983" datatype="html">
<source>Open instance in a new tab</source>
<target state="translated">在新分頁中開啟站臺</target>
<trans-unit id="9132918641931433659" datatype="html">
<source>No host found matching current filters.</source>
<target state="translated">沒有主機符合目前的過濾器。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">70</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7274241885665071790" datatype="html">
<source>Your instance is not following anyone.</source>
<target state="translated">您的站臺並未追蹤任何人。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">71</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="4774348799569692380" datatype="html">
<source>Showing <x id="INTERPOLATION"/> to <x id="INTERPOLATION_1"/> of <x id="INTERPOLATION_2"/> hosts</source>
<target state="translated">正在顯示 <x id="INTERPOLATION"/> 到 <x id="INTERPOLATION_1"/>,總共有 <x id="INTERPOLATION_2"/> 個主機</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">11</context></context-group>
</trans-unit>
- <trans-unit id="6275803119759621687" datatype="html">
- <source>Follow domains</source>
- <target state="translated">追蹤網域</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">78</context></context-group>
- </trans-unit>
- <trans-unit id="1268699198448750610" datatype="html">
- <source>Follow instances</source>
- <target state="translated">追蹤站台</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<target state="translated">動作</target>
<trans-unit id="8286337167859377104">
<source>Create user</source>
<target>建立使用者</target>
-
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">93</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.html</context><context context-type="linenumber">20</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">93</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.html</context><context context-type="linenumber">20</context></context-group>
+ </trans-unit>
<trans-unit id="8363291180171434623" datatype="html">
<source>Table parameters</source>
<target state="translated">參數表</target>
<trans-unit id="5248717555542428023">
<source>Username</source>
<target>使用者名稱</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group>
- </trans-unit>
+
+
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">83</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">111</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html</context><context context-type="linenumber">6</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+signup/+register/register-step-user.component.html</context><context context-type="linenumber">23</context></context-group></trans-unit>
<trans-unit id="5428411040014095392" datatype="html">
<source>e.g. jane_doe</source>
<target state="translated">例如:jane_doe</target>
<trans-unit id="4145496584631696119">
<source>Role</source>
<target>角色</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">136</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">114</context></context-group></trans-unit>
<trans-unit id="7046347992315328430" datatype="html">
<source>Transcoding is enabled. The video quota only takes into account <x id="START_TAG_STRONG"/>original<x id="CLOSE_TAG_STRONG"/> video size. <x id="LINE_BREAK"/> At most, this user could upload ~ <x id="INTERPOLATION"/>. </source>
<target state="translated">轉換編碼已啟用。影片配額僅考慮<x id="START_TAG_STRONG"/>原始<x id="CLOSE_TAG_STRONG"/>影片大小。<x id="LINE_BREAK"/>此使用者最多只能上傳 ~ <x id="INTERPOLATION"/>。 </target>
<trans-unit id="2622255144026150901" datatype="html">
<source>Auth plugin</source>
<target state="translated">驗證外掛程式</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context>
- <context context-type="linenumber">188</context>
- </context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-edit.component.html</context><context context-type="linenumber">188</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">121</context></context-group></trans-unit>
<trans-unit id="588099657508661970" datatype="html">
<source>None (local authentication)</source>
<target state="translated">無(本機驗證)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/moderation/video-comment-list/video-comment-list.component.html</context><context context-type="linenumber">65</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-ownership/my-ownership.component.html</context><context context-type="linenumber">18</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-abuse-list/abuse-list-table.component.html</context><context context-type="linenumber">41</context></context-group>
+ </trans-unit><trans-unit id="8390803680962035202" datatype="html">
+ <source>Follower</source><target state="new">Follower</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">24</context>
+ </context-group>
</trans-unit>
<trans-unit id="4691552465058437520" datatype="html">
<source>Commented video</source>
<trans-unit id="4917252294930256268" datatype="html">
<source>It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.</source>
<target state="translated">看起來您似乎不在 HTTPS 伺服器上。您的網路伺服器必須啟用 TLS 才能追蹤伺服器。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">81</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context><context context-type="linenumber">28</context></context-group></trans-unit>
<trans-unit id="4058814854824495833" datatype="html">
<source>Mute domains</source>
<target state="translated">靜音網域</target>
<trans-unit id="5512878593724620692" datatype="html">
<source>CHANNELS</source>
<target state="translated">頻道</target>
- <context-group purpose="location">
- <context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context>
- <context context-type="linenumber">82</context>
- </context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">81</context></context-group></trans-unit>
<trans-unit id="3666829335406793239">
<source>This account does not have channels.</source>
<target>此帳號沒有頻道。</target>
channel with the same name (<x id="PH_2" equiv-text="videoChannel.name"/>)!</source>
<target state="translated">您真的想要刪除 <x id="PH" equiv-text="videoChannel.displayName"/> 嗎?其將會刪除 <x id="PH_1" equiv-text="videoChannel.videosCount"/> 部上傳至此頻道的影片,且您將無法建立其他同名的頻道 (<x id="PH_2" equiv-text="videoChannel.name"/>)!</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">44</context></context-group>
+ </trans-unit><trans-unit id="4433306639366959484" datatype="html">
+ <source>Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</source><target state="new">Please type the name of the video channel (<x id="PH" equiv-text="videoChannel.name"/>) to confirm</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context>
+ <context context-type="linenumber">48</context>
+ </context-group>
</trans-unit>
<trans-unit id="5387007581996837469" datatype="html">
<source>My Channels</source>
<trans-unit id="6979021199788941693">
<source>Your message has been sent.</source>
<target>您的訊息已被傳送。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">89</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">88</context></context-group></trans-unit>
<trans-unit id="2072135752262464360">
<source>You already sent this form recently</source>
<target>您最近已發送此表單</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">95</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+about/about-instance/contact-admin-modal.component.ts</context><context context-type="linenumber">94</context></context-group></trans-unit>
<trans-unit id="819067926858619041" datatype="html">
<source>Account videos</source>
<target state="translated">帳號影片</target>
<target state="translated">
<x id="PH"/> 直接帳號追蹤者
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">155</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">154</context></context-group></trans-unit>
<trans-unit id="6250999352462648289" datatype="html">
<source>Report this account</source>
<target state="translated">回報此帳號</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">196</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">195</context></context-group></trans-unit>
<trans-unit id="1504521795586863905" datatype="html">
<source>VIDEOS</source>
<target state="translated">影片</target>
<trans-unit id="25349740244798533">
<source>Username copied</source>
<target>使用者名稱已複製</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">121</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">120</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">103</context></context-group></trans-unit>
<trans-unit id="9221735175659318025" datatype="html">
<source>1 subscriber</source>
<target state="translated">1 個訂閱者</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">125</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">124</context></context-group></trans-unit>
<trans-unit id="4097331874769079975" datatype="html">
<source><x id="PH"/> subscribers</source>
<target state="translated"><x id="PH"/> 個訂閱者</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">127</context></context-group>
- </trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">您追蹤的站臺</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">追蹤您的站臺</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context><context context-type="linenumber">3</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+accounts/accounts.component.ts</context><context context-type="linenumber">126</context></context-group></trans-unit>
+
+
<trans-unit id="1035838766454786107" datatype="html">
<source>Audio-only</source>
<target state="translated">僅音訊</target>
<source>Auto (via ffmpeg)</source>
<target>自動(透過 ffmpeg)</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/config/shared/config.service.ts</context><context context-type="linenumber">50</context></context-group>
+ </trans-unit><trans-unit id="3642770981085338761" datatype="html">
+ <source>Followers of your instance</source><target state="new">Followers of your instance</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="931255636742351800" datatype="html">
<source>No limit</source>
<trans-unit id="2127446333083057097" datatype="html">
<source>Domain is required.</source>
<target state="translated">網域必填。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">56</context></context-group>
- </trans-unit>
- <trans-unit id="6780793142903080663" datatype="html">
- <source>Domains entered are invalid.</source>
- <target state="translated">輸入的域名無效。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
- <trans-unit id="5886492514458202177" datatype="html">
- <source>Domains entered contain duplicates.</source>
- <target state="translated">輸入的域名包含重覆的項目。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">58</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">92</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">101</context></context-group></trans-unit><trans-unit id="7951488350851416577" datatype="html">
+ <source>Hosts entered are invalid.</source><target state="new">Hosts entered are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">93</context>
+ </context-group>
+ </trans-unit><trans-unit id="1469559036084108672" datatype="html">
+ <source>Hosts entered contain duplicates.</source><target state="new">Hosts entered contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">94</context>
+ </context-group>
+ </trans-unit><trans-unit id="5991533283446904296" datatype="html">
+ <source>Hosts or handles are invalid.</source><target state="new">Hosts or handles are invalid.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">102</context>
+ </context-group>
+ </trans-unit><trans-unit id="6759198394434886237" datatype="html">
+ <source>Hosts or handles contain duplicates.</source><target state="new">Hosts or handles contain duplicates.</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context>
+ <context context-type="linenumber">103</context>
+ </context-group>
</trans-unit>
+
+
<trans-unit id="240806681889331244">
<source>Unlimited</source>
<target>無限制</target>
<source><x id="PH"/> removed from instance followers </source>
<target><x id="PH"/> 已從站臺追蹤者中移除 </target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/followers-list/followers-list.component.ts</context><context context-type="linenumber">81</context></context-group>
+ </trans-unit><trans-unit id="6018246591673612412" datatype="html">
+ <source>Follow</source><target state="new">Follow</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">37</context>
+ </context-group>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">18</context>
+ </context-group>
+ </trans-unit><trans-unit id="3596798855644241001" datatype="html">
+ <source>1 host (without "http://"), account handle or channel handle per line</source><target state="new">1 host (without "http://"), account handle or channel handle per line</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.html</context>
+ <context context-type="linenumber">11</context>
+ </context-group>
</trans-unit>
<trans-unit id="2740793005745065895">
<source><x id="PH"/> is not valid </source>
<target>
<x id="PH"/> 無效
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/batch-domains-validators.ts</context><context context-type="linenumber">19</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">27</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/shared/form-validators/host-validators.ts</context><context context-type="linenumber">50</context></context-group></trans-unit>
<trans-unit id="2355066641781598196">
<source>Follow request(s) sent!</source>
<target>追蹤請求已傳送!</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/follow-modal.component.ts</context><context context-type="linenumber">62</context></context-group></trans-unit><trans-unit id="3459358413436264734" datatype="html">
+ <source>Your instance subscriptions</source><target state="new">Your instance subscriptions</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.html</context>
+ <context context-type="linenumber">3</context>
+ </context-group>
</trans-unit>
<trans-unit id="4245720728052819482">
<source>Do you really want to unfollow <x id="PH"/>?</source>
<target>您想要取消追蹤 <x id="PH"/> 嗎?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">57</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">47</context></context-group></trans-unit>
<trans-unit id="9160510009013134726">
<source>Unfollow</source>
<target>取消追蹤</target>
<trans-unit id="3935234189109112926">
<source>You are not following <x id="PH"/> anymore.</source>
<target>您無法再追蹤 <x id="PH"/>。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/following-list/following-list.component.ts</context><context context-type="linenumber">54</context></context-group></trans-unit>
<trans-unit id="2593763089859685916">
<source>enabled</source>
<target>已啟用</target>
<trans-unit id="1519954996184640001">
<source>Error</source>
<target>錯誤</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">104</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group>
- </trans-unit>
+
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">103</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/core/notification/notifier.service.ts</context><context context-type="linenumber">18</context></context-group></trans-unit>
<trans-unit id="5076187961693950167" datatype="html">
<source>Standard logs</source>
<target state="translated">標準日誌</target>
<trans-unit id="1886888801485703107">
<source>User <x id="PH"/> created.</source>
<target>使用者 <x id="PH"/> 已建立。</target>
-
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">76</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-create.component.ts</context><context context-type="linenumber">76</context></context-group>
+ </trans-unit>
<trans-unit id="8286337167859377104" datatype="html">
<source>Create user</source>
<target state="translated">建立使用者</target>
<target>更新使用者密碼</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-edit/user-password.component.ts</context><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="177544274549739411" datatype="html">
- <source>Following list</source>
- <target state="translated">追蹤清單</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">28</context></context-group>
- </trans-unit>
- <trans-unit id="8092429110007204784" datatype="html">
- <source>Followers list</source>
- <target state="translated">追蹤者清單</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/follows/follows.routes.ts</context><context context-type="linenumber">37</context></context-group>
- </trans-unit>
+
+
<trans-unit id="780323526182667308" datatype="html">
<source>User <x id="PH"/> updated.</source>
<target state="translated">使用者 <x id="PH"/> 已更新。</target>
<target state="translated">聯盟</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="4682675125751819107" datatype="html">
- <source>Instances you follow</source>
- <target state="translated">您追蹤的站臺</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">29</context></context-group>
- </trans-unit>
- <trans-unit id="8899833753704589712" datatype="html">
- <source>Instances following you</source>
- <target state="translated">追蹤您的站臺</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+admin/admin.component.ts</context><context context-type="linenumber">34</context></context-group>
- </trans-unit>
+
+
<trans-unit id="3767259920053407667" datatype="html">
<source>Videos will be deleted, comments will be tombstoned.</source>
<target state="translated">影片與留言都將會被刪除。</target>
<target>設定電子郵件為已驗證</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">src/app/shared/shared-moderation/user-moderation-dropdown.component.ts</context><context context-type="linenumber">281</context></context-group>
+ </trans-unit><trans-unit id="4207916966377787111" datatype="html">
+ <source>Created</source><target state="new">Created</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">115</context>
+ </context-group>
+ </trans-unit><trans-unit id="8140268298586972139" datatype="html">
+ <source>Daily quota</source><target state="new">Daily quota</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">120</context>
+ </context-group>
+ </trans-unit><trans-unit id="7910076708497708162" datatype="html">
+ <source>Last login</source><target state="new">Last login</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+admin/users/user-list/user-list.component.ts</context>
+ <context context-type="linenumber">122</context>
+ </context-group>
</trans-unit>
<trans-unit id="3403978719736970622">
<source>You cannot ban root.</source>
<trans-unit id="1137937154872046253">
<source>Video channel <x id="PH"/> created.</source>
<target>影片頻道 <x id="PH"/> 已更新。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="8723777130353305761">
<source>This name already exists on this instance.</source>
<target>此名稱已存在於此站臺上。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">73</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts</context><context context-type="linenumber">72</context></context-group></trans-unit>
<trans-unit id="7589345916094713536">
<source>Video channel <x id="PH"/> updated.</source>
<target>影片頻道 <x id="PH"/> 已更新。</target>
<target state="translated">橫幅已刪除。</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts</context><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="2575302837003821736">
- <source>Please type the display name of the video channel (<x id="PH"/>) to confirm</source>
- <target>請輸入影片頻道的顯示名稱 ( <x id="PH"/>) 以確認</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/+my-video-channels/my-video-channels.component.ts</context><context context-type="linenumber">48</context></context-group>
- </trans-unit>
+
<trans-unit id="624066830180032195">
<source>Video channel <x id="PH"/> deleted.</source>
<target>影片頻道 <x id="PH"/> 已刪除。</target>
<source>Ownership change request sent.</source>
<target>所有權變更請求已發送。</target>
<context-group purpose="location"><context context-type="sourcefile">src/app/+my-library/my-videos/modals/video-change-ownership.component.ts</context><context context-type="linenumber">64</context></context-group>
+ </trans-unit><trans-unit id="7699622144571229146" datatype="html">
+ <source>Sort by</source><target state="new">Sort by</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/+my-library/my-videos/my-videos.component.html</context>
+ <context context-type="linenumber">26</context>
+ </context-group>
</trans-unit>
<trans-unit id="3245220240937722814">
<source>My channels</source>
<target>訂閱帳號</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">704</context></context-group></trans-unit>
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+video-channels/video-channels.component.ts</context><context context-type="linenumber">71</context></context-group><context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">711</context></context-group></trans-unit>
<trans-unit id="3131904093925601441" datatype="html">
<source>PLAYLISTS</source>
<target state="translated">播放清單</target>
<trans-unit id="3779524668013120370">
<source>Go to my subscriptions</source>
<target>前往我的訂閱</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">64</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">63</context></context-group></trans-unit>
<trans-unit id="1136469849928650779">
<source>Go to my videos</source>
<target>前往我的影片</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">68</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">67</context></context-group></trans-unit>
<trans-unit id="7836683738999600376">
<source>Go to my imports</source>
<target>前往我的匯入</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="7511292153332773503">
<source>Go to my channels</source>
<target>前往我的頻道</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">76</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">75</context></context-group></trans-unit>
<trans-unit id="2013324644839511073" datatype="html">
<source>Cannot retrieve OAuth Client credentials: <x id="PH" equiv-text="error.text"/>.
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.</source>
<target state="translated">無法擷取 OAuth 客戶端憑證:<x id="PH" equiv-text="error.text"/>。請確保您已正確設定 PeerTube(config/ 目錄),特別是 "webserver" 部份。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">99</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">98</context></context-group></trans-unit>
<trans-unit id="375263728166936544">
<source>You need to reconnect.</source>
<target>您需要重新連線。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">220</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/auth/auth.service.ts</context><context context-type="linenumber">219</context></context-group></trans-unit>
<trans-unit id="2206638022166154361">
<source>Keyboard Shortcuts:</source>
<target>鍵盤快捷鍵:</target>
<context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
<context context-type="linenumber">98</context>
</context-group>
+ </trans-unit><trans-unit id="4024404994702813072" datatype="html">
+ <source>In my library</source><target state="new">In my library</target>
+ <context-group purpose="location">
+ <context context-type="sourcefile">src/app/core/menu/menu.service.ts</context>
+ <context context-type="linenumber">104</context>
+ </context-group>
</trans-unit>
<trans-unit id="232050922346936574" datatype="html">
<source>Trending</source>
<trans-unit id="1266887509445371246">
<source>Incorrect username or password.</source>
<target>不正確的使用者名稱或密碼。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">159</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">163</context></context-group></trans-unit>
<trans-unit id="6974874606619467663" datatype="html">
<source>Your account is blocked.</source>
<target state="translated">您的帳號已被封鎖。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">160</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+login/login.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="7939914198003891823" datatype="html">
<source>any language</source>
<target state="translated">任何語言</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">263</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">266</context></context-group></trans-unit>
<trans-unit id="5633144232269377096" datatype="html">
<source>hide</source>
<target state="translated">隱藏</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">298</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">301</context></context-group></trans-unit>
<trans-unit id="8603861867909474404" datatype="html">
<source>blur</source>
<target state="translated">模糊</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">302</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">305</context></context-group></trans-unit>
<trans-unit id="4534458451100881847" datatype="html">
<source>display</source>
<target state="translated">顯示</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">306</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">309</context></context-group></trans-unit>
<trans-unit id="4467323362722952678" datatype="html">
<source>Unknown</source>
<target state="translated">未知</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">193</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/menu/menu.component.ts</context><context context-type="linenumber">196</context></context-group></trans-unit>
<trans-unit id="8781423666414310853">
<source>Your password has been successfully reset!</source>
<target>您的密碼已成功重設!</target>
<trans-unit id="968295009933361070">
<source>Too many attempts, please try again after <x id="PH"/> minutes.</source>
<target>太多次嘗試,請在 <x id="PH"/> 分鐘後再試。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">67</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">66</context></context-group></trans-unit>
<trans-unit id="4965472196059235310">
<source>Too many attempts, please try again later.</source>
<target>太多次嘗試,請稍後再試。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">69</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">68</context></context-group></trans-unit>
<trans-unit id="1693549688987384699">
<source>Server error. Please retry later.</source>
<target>伺服器錯誤。請稍後重試。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">72</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/core/rest/rest-extractor.service.ts</context><context context-type="linenumber">71</context></context-group></trans-unit>
<trans-unit id="5927402622550505067" datatype="html">
<source>Subscribed to all current channels of <x id="PH"/>. You will be notified of all their new videos.</source>
<target state="translated">訂閱 <x id="PH"/> 目前的所有頻道。您將會收到它們所有的新影片。</target>
<trans-unit id="3284171506518522275">
<source>Your video was uploaded to your account and is private.</source>
<target>您的影片已上傳到您的帳號並為私人影片。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">161</context></context-group></trans-unit>
<trans-unit id="5699822024600815733">
<source>But associated data (tags, description...) will be lost, are you sure you want to leave this page?</source>
<target>但相關資料(標籤、描述等)將會遺失,您確定您想要離開此頁面嗎?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">163</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">162</context></context-group></trans-unit>
<trans-unit id="1219739004043110649">
<source>Your video is not uploaded yet, are you sure you want to leave this page?</source>
<target>您的影片尚未上傳,您確定您想要離開此頁面嗎?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">165</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">164</context></context-group></trans-unit>
<trans-unit id="6932865105766151309" datatype="html">
<source>Upload</source>
<target state="translated">上傳</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">222</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">221</context></context-group></trans-unit>
<trans-unit id="8278735427925094503">
<source>Upload <x id="PH"/> </source>
<target>上傳
<x id="PH"/>
</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">224</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">223</context></context-group></trans-unit>
<trans-unit id="5981816353437801748">
<source>Video published.</source>
<target>影片已發佈。</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">245</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-edit/video-add-components/video-upload.component.ts</context><context context-type="linenumber">244</context></context-group></trans-unit>
<trans-unit id="764164089183618119">
<source>You have unsaved changes! If you leave, your changes will be lost.</source>
<target>您有未儲存的變更!如果您離開,您的變更將會遺失。</target>
<trans-unit id="961774488937452220" datatype="html">
<source>This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="<x id="PH"/>"><x id="PH_1"/></a>?</source>
<target state="translated">此影片在此站臺上不可用。您想要重新導向至原始站臺:<a href="<x id="PH"/>"><x id="PH_1"/></a> 嗎?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">288</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">295</context></context-group></trans-unit>
<trans-unit id="5761611056224181752" datatype="html">
<source>Redirection</source>
<target state="translated">重新導向</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">289</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">296</context></context-group></trans-unit>
<trans-unit id="8858527736400081688">
<source>This video contains mature or explicit content. Are you sure you want to watch it?</source>
<target>這部影片包含成人或裸露內容。您確定您想要觀看嗎?</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">335</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">342</context></context-group></trans-unit>
<trans-unit id="3937119019020041049">
<source>Mature or explicit content</source>
<target>成人或裸露內容</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">336</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">343</context></context-group></trans-unit>
<trans-unit id="1755474755114288376" datatype="html">
<source>Up Next</source>
<target state="translated">往下</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">407</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">414</context></context-group></trans-unit>
<trans-unit id="2159130950882492111" datatype="html">
<source>Cancel</source>
<target state="translated">取消</target>
<trans-unit id="3354816756665089864" datatype="html">
<source>Autoplay is suspended</source>
<target state="translated">自動播放已暫停</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">409</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">416</context></context-group></trans-unit>
<trans-unit id="7895294730547405228" datatype="html">
<source>Enter/exit fullscreen (requires player focus)</source>
<target state="translated">進入/離開全螢幕(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">678</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group></trans-unit>
<trans-unit id="7618388257165864759" datatype="html">
<source>Play/Pause the video (requires player focus)</source>
<target state="translated">播放/暫停影片(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">679</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">686</context></context-group></trans-unit>
<trans-unit id="7761890399634216630" datatype="html">
<source>Mute/unmute the video (requires player focus)</source>
<target state="translated">靜音/解除靜音影片(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">680</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group></trans-unit>
<trans-unit id="5996585232248234904" datatype="html">
<source>Skip to a percentage of the video: 0 is 0% and 9 is 90% (requires player focus)</source>
<target state="translated">跳到影片的百分比:0 是 0%,9 是 90%(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">682</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">689</context></context-group></trans-unit>
<trans-unit id="3748765405903319998" datatype="html">
<source>Increase the volume (requires player focus)</source>
<target state="translated">增加音量(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">684</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group></trans-unit>
<trans-unit id="5810704036407159982" datatype="html">
<source>Decrease the volume (requires player focus)</source>
<target state="translated">降低音量(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">685</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">692</context></context-group></trans-unit>
<trans-unit id="2622048822548065691" datatype="html">
<source>Seek the video forward (requires player focus)</source>
<target state="translated">快轉影片(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">687</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">694</context></context-group></trans-unit>
<trans-unit id="6540078205109221153" datatype="html">
<source>Seek the video backward (requires player focus)</source>
<target state="translated">向後快轉影片(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">688</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">695</context></context-group></trans-unit>
<trans-unit id="1956491957766210808" datatype="html">
<source>Increase playback rate (requires player focus)</source>
<target state="translated">提高播放速度(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">690</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">697</context></context-group></trans-unit>
<trans-unit id="5495529997674803186" datatype="html">
<source>Decrease playback rate (requires player focus)</source>
<target state="translated">減慢播放速度(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">691</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">698</context></context-group></trans-unit>
<trans-unit id="3178343147230721210" datatype="html">
<source>Navigate in the video frame by frame (requires player focus)</source>
<target state="translated">逐畫格瀏覽影片(需要播放器焦點)</target>
- <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">693</context></context-group>
- </trans-unit>
+
+ <context-group purpose="location"><context context-type="sourcefile">src/app/+videos/+video-watch/video-watch.component.ts</context><context context-type="linenumber">700</context></context-group></trans-unit>
<trans-unit id="8025996572234182184">
<source>Like the video</source>
<target>喜歡此影片</target>
vertical-align: middle;
}
-.form-error {
+.form-error,
+.form-warning {
display: block;
- color: $red;
margin-top: 5px;
}
+.form-error {
+ color: $red;
+}
+
.input-error,
my-input-toggle-hidden ::ng-deep input {
border-color: $red !important;
import './embed.scss'
import videojs from 'video.js'
import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
HTMLServerConfig,
+ HttpStatusCode,
OAuth2ErrorCode,
ResultList,
UserRefreshToken,
videoCaptions,
inactivityTimeout: 2500,
videoViewUrl: this.getVideoUrl(videoInfo.uuid) + '/views',
+ videoShortUUID: videoInfo.shortUUID,
videoUUID: videoInfo.uuid,
isLive: videoInfo.isLive,
},
"dependencies": {
"@uploadx/core": "^4.4.0",
- "apicache": "1.6.2",
"async": "^3.0.1",
"async-lru": "^1.1.1",
"bcrypt": "5.0.1",
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.1.4",
- "@types/apicache": "^1.2.0",
"@types/async": "^3.0.0",
"@types/async-lock": "^1.1.0",
"@types/bcrypt": "^5.0.0",
"@types/chai": "^4.0.4",
"@types/chai-json-schema": "^1.4.3",
"@types/chai-xml": "^0.3.1",
- "@types/config": "^0.0.38",
+ "@types/config": "^0.0.39",
"@types/express": "4.17.9",
"@types/express-rate-limit": "^5.0.0",
"@types/fluent-ffmpeg": "^2.1.16",
"@types/lodash": "^4.14.64",
"@types/lru-cache": "^5.1.0",
"@types/magnet-uri": "^5.1.1",
- "@types/maildev": "^0.0.2",
+ "@types/maildev": "^0.0.3",
"@types/memoizee": "^0.4.2",
"@types/mkdirp": "^1.0.0",
"@types/mocha": "^8.0.3",
"source-map-support": "^0.5.0",
"supertest": "^6.0.1",
"swagger-cli": "^4.0.2",
- "ts-node": "10.0.0",
+ "ts-node": "10.1.0",
"typescript": "^4.0.5"
},
"bundlewatch": {
registerTSPaths()
import * as autocannon from 'autocannon'
-import {
- addVideoCommentReply,
- addVideoCommentThread,
- createVideoCaption,
- flushAndRunServer,
- getVideosList,
- killallServers,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '@shared/extra-utils'
-import { Video, VideoPrivacy } from '@shared/models'
import { writeJson } from 'fs-extra'
+import { createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { Video, VideoPrivacy } from '@shared/models'
-let server: ServerInfo
+let server: PeerTubeServer
let video: Video
let threadId: number
run()
.catch(err => console.error(err))
.finally(() => {
- if (server) killallServers([ server ])
+ if (server) return killallServers([ server ])
})
function buildAuthorizationHeader () {
}
async function prepare () {
- server = await flushAndRunServer(1, {
+ server = await createSingleServer(1, {
rates_limit: {
api: {
max: 5_000_000
})
await setAccessTokensToServers([ server ])
- const videoAttributes = {
+ const attributes = {
name: 'my super video',
category: 2,
nsfw: true,
}
for (let i = 0; i < 10; i++) {
- Object.assign(videoAttributes, { name: 'my super video ' + i })
- await uploadVideo(server.url, server.accessToken, videoAttributes)
+ await server.videos.upload({ attributes: { ...attributes, name: 'my super video ' + i } })
}
- const resVideos = await getVideosList(server.url)
- video = resVideos.body.data.find(v => v.name === 'my super video 1')
+ const { data } = await server.videos.list()
+ video = data.find(v => v.name === 'my super video 1')
for (let i = 0; i < 10; i++) {
const text = 'my super first comment'
- const res = await addVideoCommentThread(server.url, server.accessToken, video.id, text)
- threadId = res.body.comment.id
+ const created = await server.comments.createThread({ videoId: video.id, text })
+ threadId = created.id
const text1 = 'my super answer to thread 1'
- const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text1)
- const childCommentId = childCommentRes.body.comment.id
+ const child = await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text1 })
const text2 = 'my super answer to answer of thread 1'
- await addVideoCommentReply(server.url, server.accessToken, video.id, childCommentId, text2)
+ await server.comments.addReply({ videoId: video.id, toCommentId: child.id, text: text2 })
const text3 = 'my second answer to thread 1'
- await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text3)
+ await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text3 })
}
for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
- await createVideoCaption({
- url: server.url,
- accessToken: server.accessToken,
+ await server.captions.add({
language: caption,
videoId: video.id,
fixture: 'subtitle-good2.vtt'
feedsFiles=$(findTestFiles ./dist/server/tests/feeds)
helperFiles=$(findTestFiles ./dist/server/tests/helpers)
+ libFiles=$(findTestFiles ./dist/server/tests/lib)
miscFiles="./dist/server/tests/client.js ./dist/server/tests/misc-endpoints.js"
# Not in plugin task, it needs an index.html
pluginFiles="./dist/server/tests/plugins/html-injection.js"
- MOCHA_PARALLEL=true runTest "$1" 2 $feedsFiles $helperFiles $miscFiles $pluginFiles
+ MOCHA_PARALLEL=true runTest "$1" 2 $feedsFiles $helperFiles $miscFiles $pluginFiles $libFiles
elif [ "$1" = "cli-plugin" ]; then
npm run build:server
npm run setup:cli
serverFiles=$(findTestFiles ./dist/server/tests/api/server)
usersFiles=$(findTestFiles ./dist/server/tests/api/users)
- MOCHA_PARALLEL=true runTest "$1" 3 $serverFiles $usersFiles $liveFiles
+ MOCHA_PARALLEL=true runTest "$1" 3 $liveFiles $serverFiles $usersFiles
elif [ "$1" = "api-3" ]; then
npm run build:server
import { registerTSPaths } from '../server/helpers/register-ts-paths'
registerTSPaths()
-import { execCLI } from '@shared/extra-utils'
+import { CLICommand } from '@shared/extra-utils'
run()
.then(() => process.exit(0))
}
async function getGitContributors () {
- const output = await execCLI(`git --no-pager shortlog -sn < /dev/tty | sed 's/^\\s\\+[0-9]\\+\\s\\+//g'`)
+ const output = await CLICommand.exec(`git --no-pager shortlog -sn < /dev/tty | sed 's/^\\s\\+[0-9]\\+\\s\\+//g'`)
return output.split('\n')
.filter(l => !!l)
process.exit(-1)
})
-let currentVideoId = null
-let currentFile = null
+let currentVideoId: string
+let currentFilePath: string
process.on('SIGINT', async function () {
console.log('Cleaning up temp files')
- await remove(`${currentFile}_backup`)
- await remove(`${dirname(currentFile)}/${currentVideoId}-transcoded.mp4`)
+ await remove(`${currentFilePath}_backup`)
+ await remove(`${dirname(currentFilePath)}/${currentVideoId}-transcoded.mp4`)
process.exit(0)
})
currentVideoId = video.id
for (const file of video.VideoFiles) {
- currentFile = getVideoFilePath(video, file)
+ currentFilePath = getVideoFilePath(video, file)
const [ videoBitrate, fps, resolution ] = await Promise.all([
- getVideoFileBitrate(currentFile),
- getVideoFileFPS(currentFile),
- getVideoFileResolution(currentFile)
+ getVideoFileBitrate(currentFilePath),
+ getVideoFileFPS(currentFilePath),
+ getVideoFileResolution(currentFilePath)
])
const maxBitrate = getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)
if (isMaxBitrateExceeded) {
console.log(
'Optimizing video file %s with bitrate %s kbps (max: %s kbps)',
- basename(currentFile), videoBitrate / 1000, maxBitrate / 1000
+ basename(currentFilePath), videoBitrate / 1000, maxBitrate / 1000
)
- const backupFile = `${currentFile}_backup`
- await copy(currentFile, backupFile)
+ const backupFile = `${currentFilePath}_backup`
+ await copy(currentFilePath, backupFile)
await optimizeOriginalVideofile(video, file)
+ // Update file path, the video filename changed
+ currentFilePath = getVideoFilePath(video, file)
const originalDuration = await getDurationFromVideoFile(backupFile)
- const newDuration = await getDurationFromVideoFile(currentFile)
+ const newDuration = await getDurationFromVideoFile(currentFilePath)
if (originalDuration === newDuration) {
- console.log('Finished optimizing %s', basename(currentFile))
+ console.log('Finished optimizing %s', basename(currentFilePath))
await remove(backupFile)
continue
}
- console.log('Failed to optimize %s, restoring original', basename(currentFile))
- await move(backupFile, currentFile, { overwrite: true })
+ console.log('Failed to optimize %s, restoring original', basename(currentFilePath))
+ await move(backupFile, currentFilePath, { overwrite: true })
await createTorrentAndSetInfoHash(video, file)
await file.save()
}
import { join } from 'path'
import { createInterface } from 'readline'
import * as winston from 'winston'
-import { labelFormatter } from '../server/helpers/logger'
+import { labelFormatter, mtimeSortFilesDesc } from '../server/helpers/logger'
import { CONFIG } from '../server/initializers/config'
-import { mtimeSortFilesDesc } from '../shared/core-utils/logs/logs'
import { inspect } from 'util'
import { format as sqlFormat } from 'sql-formatter'
registerTSPaths()
import * as prompt from 'prompt'
-import { join } from 'path'
+import { join, basename } from 'path'
import { CONFIG } from '../server/initializers/config'
import { VideoModel } from '../server/models/video/video'
import { initDatabaseModels } from '../server/initializers/database'
-import { readdir, remove } from 'fs-extra'
+import { readdir, remove, stat } from 'fs-extra'
import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy'
import * as Bluebird from 'bluebird'
import { getUUIDFromFilename } from '../server/helpers/utils'
import { ActorImageModel } from '../server/models/actor/actor-image'
import { uniq, values } from 'lodash'
import { ThumbnailType } from '@shared/models'
+import { VideoFileModel } from '@server/models/video/video-file'
run()
.then(() => process.exit(0))
console.log('Detecting files to remove, it could take a while...')
toDelete = toDelete.concat(
- await pruneDirectory(CONFIG.STORAGE.VIDEOS_DIR, doesVideoExist(true)),
- await pruneDirectory(CONFIG.STORAGE.TORRENTS_DIR, doesVideoExist(true)),
+ await pruneDirectory(CONFIG.STORAGE.VIDEOS_DIR, doesWebTorrentFileExist()),
+ await pruneDirectory(CONFIG.STORAGE.TORRENTS_DIR, doesTorrentFileExist()),
await pruneDirectory(CONFIG.STORAGE.REDUNDANCY_DIR, doesRedundancyExist),
const toDelete: string[] = []
await Bluebird.map(files, async file => {
- if (await existFun(file) !== true) {
- toDelete.push(join(directory, file))
+ const filePath = join(directory, file)
+
+ if (await existFun(filePath) !== true) {
+ toDelete.push(filePath)
}
}, { concurrency: 20 })
return toDelete
}
-function doesVideoExist (keepOnlyOwned: boolean) {
- return async (file: string) => {
- const uuid = getUUIDFromFilename(file)
- const video = await VideoModel.load(uuid)
+function doesWebTorrentFileExist () {
+ return (filePath: string) => VideoFileModel.doesOwnedWebTorrentVideoFileExist(basename(filePath))
+}
- return video && (keepOnlyOwned === false || video.isOwned())
- }
+function doesTorrentFileExist () {
+ return (filePath: string) => VideoFileModel.doesOwnedTorrentFileExist(basename(filePath))
}
function doesThumbnailExist (keepOnlyOwned: boolean, type: ThumbnailType) {
- return async (file: string) => {
- const thumbnail = await ThumbnailModel.loadByFilename(file, type)
+ return async (filePath: string) => {
+ const thumbnail = await ThumbnailModel.loadByFilename(basename(filePath), type)
if (!thumbnail) return false
if (keepOnlyOwned) {
}
}
-async function doesActorImageExist (file: string) {
- const image = await ActorImageModel.loadByName(file)
+async function doesActorImageExist (filePath: string) {
+ const image = await ActorImageModel.loadByName(basename(filePath))
return !!image
}
-async function doesRedundancyExist (file: string) {
- const uuid = getUUIDFromFilename(file)
- const video = await VideoModel.loadWithFiles(uuid)
-
- if (!video) return false
-
- const isPlaylist = file.includes('.') === false
+async function doesRedundancyExist (filePath: string) {
+ const isPlaylist = (await stat(filePath)).isDirectory()
if (isPlaylist) {
+ const uuid = getUUIDFromFilename(filePath)
+ const video = await VideoModel.loadWithFiles(uuid)
+ if (!video) return false
+
const p = video.getHLSPlaylist()
if (!p) return false
return !!redundancy
}
- const resolution = parseInt(file.split('-')[5], 10)
- if (isNaN(resolution)) {
- console.error('Cannot prune %s because we cannot guess guess the resolution.', file)
- return true
- }
-
- const videoFile = video.getWebTorrentFile(resolution)
- if (!videoFile) {
- console.error('Cannot find webtorrent file of video %s - %d', video.url, resolution)
- return true
- }
+ const file = await VideoFileModel.loadByFilename(basename(filePath))
+ if (!file) return false
- const redundancy = await VideoRedundancyModel.loadLocalByFileId(videoFile.id)
+ const redundancy = await VideoRedundancyModel.loadLocalByFileId(file.id)
return !!redundancy
}
import { VideoCommentModel } from '../server/models/video/video-comment'
import { AccountModel } from '../server/models/account/account'
import { VideoChannelModel } from '../server/models/video/video-channel'
-import { VideoStreamingPlaylistModel } from '../server/models/video/video-streaming-playlist'
import { initDatabaseModels } from '../server/initializers/database'
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
import { getServerActor } from '@server/models/application/application'
for (const file of video.VideoFiles) {
console.log('Updating torrent file %s of video %s.', file.resolution, video.uuid)
await createTorrentAndSetInfoHash(video, file)
+
+ await file.save()
}
- for (const playlist of video.VideoStreamingPlaylists) {
- playlist.playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
- playlist.segmentsSha256Url = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid, video.isLive)
+ const playlist = video.getHLSPlaylist()
+ for (const file of (playlist?.VideoFiles || [])) {
+ console.log('Updating fragmented torrent file %s of video %s.', file.resolution, video.uuid)
+
+ await createTorrentAndSetInfoHash(video, file)
- await playlist.save()
+ await file.save()
}
}
}
import { Hooks } from './server/lib/plugins/hooks'
import { PluginManager } from './server/lib/plugins/plugin-manager'
import { LiveManager } from './server/lib/live'
-import { HttpStatusCode } from './shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from './shared/models/http/http-error-codes'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
import { ServerConfigManager } from '@server/lib/server-config-manager'
updateStreamingPlaylistsInfohashesIfNeeded()
.catch(err => logger.error('Cannot update streaming playlist infohashes.', { err }))
- if (cliOptions.plugins) await PluginManager.Instance.registerPluginsAndThemes()
-
LiveManager.Instance.init()
if (CONFIG.LIVE.ENABLED) LiveManager.Instance.run()
// Make server listening
- server.listen(port, hostname, () => {
+ server.listen(port, hostname, async () => {
+ if (cliOptions.plugins) {
+ try {
+ await PluginManager.Instance.registerPluginsAndThemes()
+ } catch (err) {
+ logger.error('Cannot register plugins and themes.', { err })
+ }
+ }
+
logger.info('HTTP server listening on %s:%d', hostname, port)
logger.info('Web server: %s', WEBSERVER.URL)
videosCustomGetValidator,
videosShareValidator
} from '../../middlewares'
-import { cacheRoute } from '../../middlewares/cache'
+import { cacheRoute } from '../../middlewares/cache/cache'
import { getAccountVideoRateValidatorFactory, videoCommentGetValidator } from '../../middlewares/validators'
import { videoFileRedundancyGetValidator, videoPlaylistRedundancyGetValidator } from '../../middlewares/validators/redundancy'
import { videoPlaylistElementAPGetValidator, videoPlaylistsGetValidator } from '../../middlewares/validators/videos/video-playlists'
activityPubClientRouter.get(
[ '/videos/watch/:id', '/w/:id' ],
executeIfActivityPub,
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS),
asyncMiddleware(videosCustomGetValidator('all')),
asyncMiddleware(videoController)
)
import * as express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { Activity, ActivityPubCollection, ActivityPubOrderedCollection, RootActivity } from '../../../shared'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isActivityValid } from '../../helpers/custom-validators/activitypub/activity'
import { logger } from '../../helpers/logger'
import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares'
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
import { getServerActor } from '@server/models/application/application'
import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
import { AbuseCreate, AbuseState, UserRight } from '../../../shared'
import { getFormattedObjects } from '../../helpers/utils'
import { sequelizeTypescript } from '../../initializers/database'
import * as express from 'express'
+import { pickCommonVideoQuery } from '@server/helpers/query'
import { getServerActor } from '@server/models/application/application'
-import { VideosWithSearchCommonQuery } from '@shared/models'
import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
import { getFormattedObjects } from '../../helpers/utils'
import { JobQueue } from '../../lib/job-queue'
const account = res.locals.account
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
const countVideos = getCountVideos(req)
- const query = req.query as VideosWithSearchCommonQuery
+ const query = pickCommonVideoQuery(req.query)
const apiOptions = await Hooks.wrapObject({
+ ...query,
+
followerActorId,
- start: query.start,
- count: query.count,
- sort: query.sort,
+ search: req.query.search,
includeLocalVideos: true,
- categoryOneOf: query.categoryOneOf,
- licenceOneOf: query.licenceOneOf,
- languageOneOf: query.languageOneOf,
- tagsOneOf: query.tagsOneOf,
- tagsAllOf: query.tagsAllOf,
- filter: query.filter,
- isLive: query.isLive,
nsfw: buildNSFWFilter(res, query.nsfw),
withFiles: false,
accountId: account.id,
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
- countVideos,
- search: query.search
+ countVideos
}, 'filter:api.accounts.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
import * as express from 'express'
-import { asyncMiddleware, authenticate } from '../../middlewares'
+import { removeComment } from '@server/lib/video-comment'
import { bulkRemoveCommentsOfValidator } from '@server/middlewares/validators/bulk'
import { VideoCommentModel } from '@server/models/video/video-comment'
-import { removeComment } from '@server/lib/video-comment'
+import { HttpStatusCode } from '@shared/models'
import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { asyncMiddleware, authenticate } from '../../middlewares'
const bulkRouter = express.Router()
-import { ServerConfigManager } from '@server/lib/server-config-manager'
import * as express from 'express'
import { remove, writeJSON } from 'fs-extra'
import { snakeCase } from 'lodash'
import validator from 'validator'
+import { ServerConfigManager } from '@server/lib/server-config-manager'
import { UserRight } from '../../../shared'
import { About } from '../../../shared/models/server/about.model'
import { CustomConfig } from '../../../shared/models/server/custom-config.model'
import * as express from 'express'
import { ServerConfigManager } from '@server/lib/server-config-manager'
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
-import { HttpStatusCode } from '@shared/core-utils'
-import { UserRight } from '@shared/models'
+import { HttpStatusCode, UserRight } from '@shared/models'
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
const customPageRouter = express.Router()
import * as cors from 'cors'
import * as express from 'express'
import * as RateLimit from 'express-rate-limit'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models'
import { badRequest } from '../../helpers/express-utils'
import { CONFIG } from '../../initializers/config'
import { abuseRouter } from './abuse'
import * as express from 'express'
import { OAuthClientLocal } from '../../../shared'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { logger } from '../../helpers/logger'
import { CONFIG } from '../../initializers/config'
import { asyncMiddleware, openapiOperationDoc } from '../../middlewares'
import * as express from 'express'
+import * as memoizee from 'memoizee'
+import { logger } from '@server/helpers/logger'
+import { Hooks } from '@server/lib/plugins/hooks'
+import { VideoModel } from '@server/models/video/video'
+import { CategoryOverview, ChannelOverview, TagOverview, VideosOverview } from '../../../shared/models/overviews'
import { buildNSFWFilter } from '../../helpers/express-utils'
-import { VideoModel } from '../../models/video/video'
+import { MEMOIZE_TTL, OVERVIEWS } from '../../initializers/constants'
import { asyncMiddleware, optionalAuthenticate, videosOverviewValidator } from '../../middlewares'
import { TagModel } from '../../models/video/tag'
-import { CategoryOverview, ChannelOverview, TagOverview, VideosOverview } from '../../../shared/models/overviews'
-import { MEMOIZE_TTL, OVERVIEWS } from '../../initializers/constants'
-import * as memoizee from 'memoizee'
-import { logger } from '@server/helpers/logger'
const overviewsRouter = express.Router()
res: express.Response,
where: { videoChannelId?: number, tagsOneOf?: string[], categoryOneOf?: number[] }
) {
- const query = Object.assign({
+ const query = await Hooks.wrapObject({
start: 0,
count: 12,
sort: '-createdAt',
nsfw: buildNSFWFilter(res),
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
withFiles: false,
- countVideos: false
- }, where)
+ countVideos: false,
+
+ ...where
+ }, 'filter:api.overviews.videos.list.params')
- const { data } = await VideoModel.listForApi(query)
+ const { data } = await Hooks.wrapPromiseFun(
+ VideoModel.listForApi,
+ query,
+ 'filter:api.overviews.videos.list.result'
+ )
return data.map(d => d.toFormattedJSON())
}
updatePluginSettingsValidator
} from '@server/middlewares/validators/plugins'
import { PluginModel } from '@server/models/server/plugin'
-import { HttpStatusCode } from '@shared/core-utils'
import {
+ HttpStatusCode,
InstallOrUpdatePlugin,
ManagePlugin,
PeertubePluginIndexList,
import * as express from 'express'
import { sanitizeUrl } from '@server/helpers/core-utils'
+import { pickSearchChannelQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
import { CONFIG } from '@server/initializers/config'
import { WEBSERVER } from '@server/initializers/constants'
import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
import { getServerActor } from '@server/models/application/application'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { ResultList, VideoChannel } from '@shared/models'
-import { VideoChannelsSearchQuery } from '../../../../shared/models/search'
+import { HttpStatusCode, ResultList, VideoChannel } from '@shared/models'
+import { VideoChannelsSearchQueryAfterSanitize } from '../../../../shared/models/search'
import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
// ---------------------------------------------------------------------------
function searchVideoChannels (req: express.Request, res: express.Response) {
- const query: VideoChannelsSearchQuery = req.query
- const search = query.search
+ const query = pickSearchChannelQuery(req.query)
+ let search = query.search || ''
const parts = search.split('@')
if (isURISearch(search) || isWebfingerSearch) return searchVideoChannelURI(search, isWebfingerSearch, res)
// @username -> username to search in DB
- if (query.search.startsWith('@')) query.search = query.search.replace(/^@/, '')
+ if (search.startsWith('@')) search = search.replace(/^@/, '')
if (isSearchIndexSearch(query)) {
return searchVideoChannelsIndex(query, res)
return searchVideoChannelsDB(query, res)
}
-async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: express.Response) {
+async function searchVideoChannelsIndex (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) {
const result = await buildMutedForSearchIndex(res)
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-channels.index.list.params')
}
}
-async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: express.Response) {
+async function searchVideoChannelsDB (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) {
const serverActor = await getServerActor()
const apiOptions = await Hooks.wrapObject({
- actorId: serverActor.id,
- search: query.search,
- start: query.start,
- count: query.count,
- sort: query.sort
+ ...query,
+
+ actorId: serverActor.id
}, 'filter:api.search.video-channels.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
import { sanitizeUrl } from '@server/helpers/core-utils'
import { isUserAbleToSearchRemoteURI } from '@server/helpers/express-utils'
import { logger } from '@server/helpers/logger'
+import { pickSearchPlaylistQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
import { getFormattedObjects } from '@server/helpers/utils'
import { CONFIG } from '@server/initializers/config'
+import { WEBSERVER } from '@server/initializers/constants'
import { getOrCreateAPVideoPlaylist } from '@server/lib/activitypub/playlists/get'
import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
import { getServerActor } from '@server/models/application/application'
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { MVideoPlaylistFullSummary } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
-import { ResultList, VideoPlaylist, VideoPlaylistsSearchQuery } from '@shared/models'
+import { HttpStatusCode, ResultList, VideoPlaylist, VideoPlaylistsSearchQueryAfterSanitize } from '@shared/models'
import {
asyncMiddleware,
openapiOperationDoc,
videoPlaylistsListSearchValidator,
videoPlaylistsSearchSortValidator
} from '../../../middlewares'
-import { WEBSERVER } from '@server/initializers/constants'
const searchPlaylistsRouter = express.Router()
// ---------------------------------------------------------------------------
function searchVideoPlaylists (req: express.Request, res: express.Response) {
- const query: VideoPlaylistsSearchQuery = req.query
+ const query = pickSearchPlaylistQuery(req.query)
const search = query.search
if (isURISearch(search)) return searchVideoPlaylistsURI(search, res)
return searchVideoPlaylistsDB(query, res)
}
-async function searchVideoPlaylistsIndex (query: VideoPlaylistsSearchQuery, res: express.Response) {
+async function searchVideoPlaylistsIndex (query: VideoPlaylistsSearchQueryAfterSanitize, res: express.Response) {
const result = await buildMutedForSearchIndex(res)
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-playlists.index.list.params')
}
}
-async function searchVideoPlaylistsDB (query: VideoPlaylistsSearchQuery, res: express.Response) {
+async function searchVideoPlaylistsDB (query: VideoPlaylistsSearchQueryAfterSanitize, res: express.Response) {
const serverActor = await getServerActor()
const apiOptions = await Hooks.wrapObject({
- followerActorId: serverActor.id,
- search: query.search,
- start: query.start,
- count: query.count,
- sort: query.sort
+ ...query,
+
+ followerActorId: serverActor.id
}, 'filter:api.search.video-playlists.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
import * as express from 'express'
import { sanitizeUrl } from '@server/helpers/core-utils'
+import { pickSearchVideoQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
import { CONFIG } from '@server/initializers/config'
import { WEBSERVER } from '@server/initializers/constants'
import { getOrCreateAPVideo } from '@server/lib/activitypub/videos'
import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { ResultList, Video } from '@shared/models'
-import { VideosSearchQuery } from '../../../../shared/models/search'
+import { HttpStatusCode, ResultList, Video } from '@shared/models'
+import { VideosSearchQueryAfterSanitize } from '../../../../shared/models/search'
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
// ---------------------------------------------------------------------------
function searchVideos (req: express.Request, res: express.Response) {
- const query: VideosSearchQuery = req.query
+ const query = pickSearchVideoQuery(req.query)
const search = query.search
if (isURISearch(search)) {
return searchVideosDB(query, res)
}
-async function searchVideosIndex (query: VideosSearchQuery, res: express.Response) {
+async function searchVideosIndex (query: VideosSearchQueryAfterSanitize, res: express.Response) {
const result = await buildMutedForSearchIndex(res)
- let body: VideosSearchQuery = Object.assign(query, result)
+ let body = { ...query, ...result }
// Use the default instance NSFW policy if not specified
if (!body.nsfw) {
}
}
-async function searchVideosDB (query: VideosSearchQuery, res: express.Response) {
- const apiOptions = await Hooks.wrapObject(Object.assign(query, {
+async function searchVideosDB (query: VideosSearchQueryAfterSanitize, res: express.Response) {
+ const apiOptions = await Hooks.wrapObject({
+ ...query,
+
includeLocalVideos: true,
- nsfw: buildNSFWFilter(res, query.nsfw),
filter: query.filter,
- user: res.locals.oauth ? res.locals.oauth.token.User : undefined
- }), 'filter:api.search.videos.local.list.params')
+
+ nsfw: buildNSFWFilter(res, query.nsfw),
+ user: res.locals.oauth
+ ? res.locals.oauth.token.User
+ : undefined
+ }, 'filter:api.search.videos.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.searchAndPopulateAccountAndServer,
import * as express from 'express'
-import { asyncMiddleware, contactAdministratorValidator } from '../../../middlewares'
-import { Redis } from '../../../lib/redis'
-import { Emailer } from '../../../lib/emailer'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { ContactForm } from '../../../../shared/models/server'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { Emailer } from '../../../lib/emailer'
+import { Redis } from '../../../lib/redis'
+import { asyncMiddleware, contactAdministratorValidator } from '../../../middlewares'
const contactRouter = express.Router()
async function contactAdministrator (req: express.Request, res: express.Response) {
const data = req.body as ContactForm
- await Emailer.Instance.addContactFormJob(data.fromEmail, data.fromName, data.subject, data.body)
+ Emailer.Instance.addContactFormJob(data.fromEmail, data.fromName, data.subject, data.body)
await Redis.Instance.setContactFormIp(req.ip)
+import * as express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { RemoveDanglingResumableUploadsScheduler } from '@server/lib/schedulers/remove-dangling-resumable-uploads-scheduler'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-import { SendDebugCommand } from '@shared/models'
-import * as express from 'express'
+import { Debug, SendDebugCommand } from '@shared/models'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users'
import { authenticate, ensureUserHasRight } from '../../../middlewares'
return res.json({
ip: req.ip,
activityPubMessagesWaiting: InboxManager.Instance.getActivityPubMessagesWaiting()
- })
+ } as Debug)
}
async function runCommand (req: express.Request, res: express.Response) {
import * as express from 'express'
import { getServerActor } from '@server/models/application/application'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users'
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
removeFollowingValidator
} from '../../../middlewares/validators'
import { ActorFollowModel } from '../../../models/actor/actor-follow'
+import { ServerFollowCreate } from '@shared/models'
const serverFollowsRouter = express.Router()
serverFollowsRouter.get('/following',
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
followValidator,
setBodyHostsPort,
- asyncMiddleware(followInstance)
+ asyncMiddleware(addFollow)
)
-serverFollowsRouter.delete('/following/:host',
+serverFollowsRouter.delete('/following/:hostOrHandle',
authenticate,
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
asyncMiddleware(removeFollowingValidator),
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
-async function followInstance (req: express.Request, res: express.Response) {
- const hosts = req.body.hosts as string[]
+async function addFollow (req: express.Request, res: express.Response) {
+ const { hosts, handles } = req.body as ServerFollowCreate
const follower = await getServerActor()
for (const host of hosts) {
JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
}
+ for (const handle of handles) {
+ const [ name, host ] = handle.split('@')
+
+ const payload = {
+ host,
+ name,
+ followerActorId: follower.id
+ }
+
+ JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
+ }
+
return res.status(HttpStatusCode.NO_CONTENT_204).end()
}
import * as express from 'express'
+import { contactRouter } from './contact'
+import { debugRouter } from './debug'
import { serverFollowsRouter } from './follows'
-import { statsRouter } from './stats'
+import { logsRouter } from './logs'
import { serverRedundancyRouter } from './redundancy'
import { serverBlocklistRouter } from './server-blocklist'
-import { contactRouter } from './contact'
-import { logsRouter } from './logs'
-import { debugRouter } from './debug'
+import { statsRouter } from './stats'
const serverRouter = express.Router()
import * as express from 'express'
-import { UserRight } from '../../../../shared/models/users'
-import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
-import { mtimeSortFilesDesc } from '../../../../shared/core-utils/logs/logs'
import { readdir, readFile } from 'fs-extra'
-import { AUDIT_LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS, LOG_FILENAME } from '../../../initializers/constants'
import { join } from 'path'
-import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs'
+import { logger, mtimeSortFilesDesc } from '@server/helpers/logger'
import { LogLevel } from '../../../../shared/models/server/log-level.type'
+import { UserRight } from '../../../../shared/models/users'
import { CONFIG } from '../../../initializers/config'
-import { logger } from '@server/helpers/logger'
+import { AUDIT_LOG_FILENAME, LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers/constants'
+import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
+import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs'
const logsRouter = express.Router()
import * as express from 'express'
+import { JobQueue } from '@server/lib/job-queue'
+import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users'
+import { logger } from '../../../helpers/logger'
+import { removeRedundanciesOfServer, removeVideoRedundancy } from '../../../lib/redundancy'
import {
asyncMiddleware,
authenticate,
videoRedundanciesSortValidator
} from '../../../middlewares'
import {
- listVideoRedundanciesValidator,
- updateServerRedundancyValidator,
addVideoRedundancyValidator,
- removeVideoRedundancyValidator
+ listVideoRedundanciesValidator,
+ removeVideoRedundancyValidator,
+ updateServerRedundancyValidator
} from '../../../middlewares/validators/redundancy'
-import { removeRedundanciesOfServer, removeVideoRedundancy } from '../../../lib/redundancy'
-import { logger } from '../../../helpers/logger'
-import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
-import { JobQueue } from '@server/lib/job-queue'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const serverRedundancyRouter = express.Router()
import 'multer'
import * as express from 'express'
import { logger } from '@server/helpers/logger'
-import { UserNotificationModel } from '@server/models/user/user-notification'
import { getServerActor } from '@server/models/application/application'
+import { UserNotificationModel } from '@server/models/user/user-notification'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users'
import { getFormattedObjects } from '../../../helpers/utils'
import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
} from '../../../middlewares/validators'
import { AccountBlocklistModel } from '../../../models/account/account-blocklist'
import { ServerBlocklistModel } from '../../../models/server/server-blocklist'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const serverBlocklistRouter = express.Router()
import { StatsManager } from '@server/lib/stat-manager'
import { ROUTE_CACHE_LIFETIME } from '../../../initializers/constants'
import { asyncMiddleware } from '../../../middlewares'
-import { cacheRoute } from '../../../middlewares/cache'
+import { cacheRoute } from '../../../middlewares/cache/cache'
const statsRouter = express.Router()
statsRouter.get('/stats',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.STATS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.STATS),
asyncMiddleware(getStats)
)
import { Hooks } from '@server/lib/plugins/hooks'
import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
import { MUser, MUserAccountDefault } from '@server/types/models'
-import { UserCreate, UserRight, UserRole, UserUpdate } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { UserCreate, UserCreateResult, UserRight, UserRole, UserUpdate } from '../../../../shared'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
import { UserRegister } from '../../../../shared/models/users/user-register.model'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
account: {
id: account.id
}
- }
+ } as UserCreateResult
})
}
import * as express from 'express'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '@server/helpers/audit-logger'
import { Hooks } from '@server/lib/plugins/hooks'
+import { AttributesOnly } from '@shared/core-utils'
import { ActorImageType, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model'
import { createReqFiles } from '../../../helpers/express-utils'
import { getFormattedObjects } from '../../../helpers/utils'
import { UserModel } from '../../../models/user/user'
import { VideoModel } from '../../../models/video/video'
import { VideoImportModel } from '../../../models/video/video-import'
-import { AttributesOnly } from '@shared/core-utils'
const auditLogger = auditLoggerFactory('users')
-import * as express from 'express'
import 'multer'
+import * as express from 'express'
+import { logger } from '@server/helpers/logger'
+import { UserNotificationModel } from '@server/models/user/user-notification'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { getFormattedObjects } from '../../../helpers/utils'
+import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
unblockServerByAccountValidator
} from '../../../middlewares/validators'
import { AccountBlocklistModel } from '../../../models/account/account-blocklist'
-import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
import { ServerBlocklistModel } from '../../../models/server/server-blocklist'
-import { UserNotificationModel } from '@server/models/user/user-notification'
-import { logger } from '@server/helpers/logger'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const myBlocklistRouter = express.Router()
import * as express from 'express'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
+import { getFormattedObjects } from '../../../helpers/utils'
+import { sequelizeTypescript } from '../../../initializers/database'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
userHistoryListValidator,
userHistoryRemoveValidator
} from '../../../middlewares'
-import { getFormattedObjects } from '../../../helpers/utils'
import { UserVideoHistoryModel } from '../../../models/user/user-video-history'
-import { sequelizeTypescript } from '../../../initializers/database'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const myVideosHistoryRouter = express.Router()
import 'multer'
import * as express from 'express'
import { UserNotificationModel } from '@server/models/user/user-notification'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserNotificationSetting } from '../../../../shared/models/users'
import { getFormattedObjects } from '../../../helpers/utils'
import {
import 'multer'
import * as express from 'express'
+import { pickCommonVideoQuery } from '@server/helpers/query'
import { sendUndoFollow } from '@server/lib/activitypub/send'
import { VideoChannelModel } from '@server/models/video/video-channel'
-import { VideosCommonQuery } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
import { getFormattedObjects } from '../../../helpers/utils'
import { WEBSERVER } from '../../../initializers/constants'
async function getUserSubscriptionVideos (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User
const countVideos = getCountVideos(req)
- const query = req.query as VideosCommonQuery
+ const query = pickCommonVideoQuery(req.query)
const resultList = await VideoModel.listForApi({
- start: query.start,
- count: query.count,
- sort: query.sort,
+ ...query,
+
includeLocalVideos: false,
- categoryOneOf: query.categoryOneOf,
- licenceOneOf: query.licenceOneOf,
- languageOneOf: query.languageOneOf,
- tagsOneOf: query.tagsOneOf,
- tagsAllOf: query.tagsAllOf,
nsfw: buildNSFWFilter(res, query.nsfw),
- filter: query.filter,
withFiles: false,
followerActorId: user.Account.Actor.id,
user,
import * as express from 'express'
+import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
import { asyncMiddleware, authenticate } from '../../../middlewares'
import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists'
import { VideoPlaylistModel } from '../../../models/video/video-playlist'
-import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
const myVideoPlaylistsRouter = express.Router()
import * as express from 'express'
+import { pickCommonVideoQuery } from '@server/helpers/query'
import { Hooks } from '@server/lib/plugins/hooks'
import { getServerActor } from '@server/models/application/application'
import { MChannelBannerAccountDefault } from '@server/types/models'
-import { ActorImageType, VideoChannelCreate, VideoChannelUpdate, VideosCommonQuery } from '../../../shared'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { ActorImageType, VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../helpers/database-utils'
import { buildNSFWFilter, createReqFiles, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
const videoChannelInstance = res.locals.videoChannel
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
const countVideos = getCountVideos(req)
- const query = req.query as VideosCommonQuery
+ const query = pickCommonVideoQuery(req.query)
const apiOptions = await Hooks.wrapObject({
+ ...query,
+
followerActorId,
- start: query.start,
- count: query.count,
- sort: query.sort,
includeLocalVideos: true,
- categoryOneOf: query.categoryOneOf,
- licenceOneOf: query.licenceOneOf,
- languageOneOf: query.languageOneOf,
- tagsOneOf: query.tagsOneOf,
- tagsAllOf: query.tagsAllOf,
- filter: query.filter,
nsfw: buildNSFWFilter(res, query.nsfw),
withFiles: false,
videoChannelId: videoChannelInstance.id,
import { Hooks } from '@server/lib/plugins/hooks'
import { getServerActor } from '@server/models/application/application'
import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/types/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { VideoPlaylistCreateResult, VideoPlaylistElementCreateResult } from '@shared/models'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { VideoPlaylistCreate } from '../../../shared/models/videos/playlist/video-playlist-create.model'
import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model'
import { VideoPlaylistElementUpdate } from '../../../shared/models/videos/playlist/video-playlist-element-update.model'
id: videoPlaylistCreated.id,
shortUUID: uuidToShort(videoPlaylistCreated.uuid),
uuid: videoPlaylistCreated.uuid
- }
+ } as VideoPlaylistCreateResult
})
}
return res.json({
videoPlaylistElement: {
id: playlistElement.id
- }
- }).end()
+ } as VideoPlaylistElementCreateResult
+ })
}
async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {
import * as express from 'express'
import { blacklistVideo, unblacklistVideo } from '@server/lib/video-blacklist'
import { UserRight, VideoBlacklistCreate } from '../../../../shared'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database'
videosBlacklistUpdateValidator
} from '../../../middlewares'
import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const blacklistRouter = express.Router()
import * as express from 'express'
import { MVideoCaption } from '@server/types/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
import { createReqFiles } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger'
import * as express from 'express'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-import { ResultList, ThreadsResultList, UserRight } from '../../../../shared/models'
-import { VideoCommentCreate } from '../../../../shared/models/videos/comment/video-comment.model'
+import { ResultList, ThreadsResultList, UserRight, VideoCommentCreate } from '../../../../shared/models'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
+import { VideoCommentThreads } from '../../../../shared/models/videos/comment/video-comment.model'
import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database'
return res.json({
...getFormattedObjects(resultList.data, resultList.total),
totalNotDeletedComments: resultList.totalNotDeletedComments
- })
+ } as VideoCommentThreads)
}
async function listVideoThreadComments (req: express.Request, res: express.Response) {
import * as express from 'express'
import toInt from 'validator/lib/toInt'
+import { pickCommonVideoQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
import { LiveManager } from '@server/lib/live'
import { openapiOperationDoc } from '@server/middlewares/doc'
import { getServerActor } from '@server/models/application/application'
import { MVideoAccountLight } from '@server/types/models'
-import { VideosCommonQuery } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs'
+import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger'
}
async function listVideos (req: express.Request, res: express.Response) {
- const query = req.query as VideosCommonQuery
+ const query = pickCommonVideoQuery(req.query)
const countVideos = getCountVideos(req)
const apiOptions = await Hooks.wrapObject({
- start: query.start,
- count: query.count,
- sort: query.sort,
+ ...query,
+
includeLocalVideos: true,
- categoryOneOf: query.categoryOneOf,
- licenceOneOf: query.licenceOneOf,
- languageOneOf: query.languageOneOf,
- tagsOneOf: query.tagsOneOf,
- tagsAllOf: query.tagsAllOf,
nsfw: buildNSFWFilter(res, query.nsfw),
- isLive: query.isLive,
- filter: query.filter,
withFiles: false,
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
countVideos
import { VideoLiveModel } from '@server/models/video/video-live'
import { MVideoDetails, MVideoFullLight } from '@server/types/models'
import { LiveVideoCreate, LiveVideoUpdate, VideoState } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers/database'
import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail'
import * as express from 'express'
+import { MVideoFullLight } from '@server/types/models'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
+import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
import { logger } from '../../../helpers/logger'
+import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database'
+import { sendUpdateVideo } from '../../../lib/activitypub/send'
+import { changeVideoChannelShare } from '../../../lib/activitypub/share'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
videosChangeOwnershipValidator,
videosTerminateChangeOwnershipValidator
} from '../../../middlewares'
+import { VideoModel } from '../../../models/video/video'
import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership'
-import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
import { VideoChannelModel } from '../../../models/video/video-channel'
-import { getFormattedObjects } from '../../../helpers/utils'
-import { changeVideoChannelShare } from '../../../lib/activitypub/share'
-import { sendUpdateVideo } from '../../../lib/activitypub/send'
-import { VideoModel } from '../../../models/video/video'
-import { MVideoFullLight } from '@server/types/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const ownershipVideoRouter = express.Router()
import * as express from 'express'
import { UserVideoRateUpdate } from '../../../../shared'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger'
import { VIDEO_RATE_TYPES } from '../../../initializers/constants'
+import { sequelizeTypescript } from '../../../initializers/database'
import { getLocalRateUrl, sendVideoRateChange } from '../../../lib/activitypub/video-rates'
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoUpdateRateValidator } from '../../../middlewares'
import { AccountModel } from '../../../models/account/account'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
-import { sequelizeTypescript } from '../../../initializers/database'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const rateVideoRouter = express.Router()
import { Transaction } from 'sequelize/types'
import { changeVideoChannelShare } from '@server/lib/activitypub/share'
import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
+import { openapiOperationDoc } from '@server/middlewares/doc'
import { FilteredModelAttributes } from '@server/types'
import { MVideoFullLight } from '@server/types/models'
import { VideoUpdate } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs'
+import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../../helpers/database-utils'
import { createReqFiles } from '../../../helpers/express-utils'
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares'
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
import { VideoModel } from '../../../models/video/video'
-import { openapiOperationDoc } from '@server/middlewares/doc'
const lTags = loggerTagsFactory('api', 'video')
const auditLogger = auditLoggerFactory('videos')
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url'
import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
-import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
+import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
import { openapiOperationDoc } from '@server/middlewares/doc'
import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
import { uploadx } from '@uploadx/core'
import { VideoCreate, VideoState } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs'
+import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { createReqFiles } from '../../../helpers/express-utils'
})
createTorrentFederate(video, videoFile)
+ .then(() => {
+ if (video.state !== VideoState.TO_TRANSCODE) return
- if (video.state === VideoState.TO_TRANSCODE) {
- await addOptimizeOrMergeAudioJob(videoCreated, videoFile, user)
- }
+ return addOptimizeOrMergeAudioJob(videoCreated, videoFile, user)
+ })
+ .catch(err => logger.error('Cannot add optimize/merge audio job for %s.', videoCreated.uuid, { err, ...lTags(videoCreated.uuid) }))
Hooks.runAction('action:api.video.uploaded', { video: videoCreated })
videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution
}
- videoFile.filename = generateVideoFilename(video, false, videoFile.resolution, videoFile.extname)
+ videoFile.filename = generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname)
return videoFile
}
return refreshedFile.save()
}
-function createTorrentFederate (video: MVideoFullLight, videoFile: MVideoFile): void {
+function createTorrentFederate (video: MVideoFullLight, videoFile: MVideoFile) {
// Create the torrent file in async way because it could be long
- createTorrentAndSetInfoHashAsync(video, videoFile)
+ return createTorrentAndSetInfoHashAsync(video, videoFile)
.catch(err => logger.error('Cannot create torrent file for video %s', video.url, { err, ...lTags(video.uuid) }))
.then(() => VideoModel.loadAndPopulateAccountAndServerAndTags(video.id))
.then(refreshedVideo => {
import * as express from 'express'
import { UserWatchingVideo } from '../../../../shared'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
videoWatchingValidator
} from '../../../middlewares'
import { UserVideoHistoryModel } from '../../../models/user/user-video-history'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const watchingRouter = express.Router()
import * as express from 'express'
-import { asyncMiddleware } from '../middlewares'
-import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants'
+import { truncate } from 'lodash'
import { SitemapStream, streamToPromise } from 'sitemap'
+import { buildNSFWFilter } from '../helpers/express-utils'
+import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants'
+import { asyncMiddleware } from '../middlewares'
+import { cacheRoute } from '../middlewares/cache/cache'
+import { AccountModel } from '../models/account/account'
import { VideoModel } from '../models/video/video'
import { VideoChannelModel } from '../models/video/video-channel'
-import { AccountModel } from '../models/account/account'
-import { cacheRoute } from '../middlewares/cache'
-import { buildNSFWFilter } from '../helpers/express-utils'
-import { truncate } from 'lodash'
const botsRouter = express.Router()
// Special route that add OpenGraph and oEmbed tags
// Do not use a template engine for a so little thing
botsRouter.use('/sitemap.xml',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.SITEMAP)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.SITEMAP),
asyncMiddleware(getSitemap)
)
})
return data.map(v => ({
- url: WEBSERVER.URL + '/w/' + v.uuid,
+ url: WEBSERVER.URL + v.getWatchStaticPath(),
video: [
{
title: v.name,
// Sitemap description should be < 2000 characters
description: truncate(v.description || v.name, { length: 2000, omission: '...' }),
- player_loc: WEBSERVER.URL + '/videos/embed/' + v.uuid,
+ player_loc: WEBSERVER.URL + v.getEmbedStaticPath(),
thumbnail_loc: WEBSERVER.URL + v.getMiniatureStaticPath()
}
]
import { logger } from '@server/helpers/logger'
import { CONFIG } from '@server/initializers/config'
import { Hooks } from '@server/lib/plugins/hooks'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
import { root } from '../helpers/core-utils'
import { STATIC_MAX_AGE } from '../initializers/constants'
import { Hooks } from '@server/lib/plugins/hooks'
import { getVideoFilePath } from '@server/lib/video-paths'
import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { VideoStreamingPlaylistType } from '@shared/models'
+import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models'
import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
import { asyncMiddleware, videosDownloadValidator } from '../middlewares'
videosSortValidator,
videoSubscriptionFeedsValidator
} from '../middlewares'
-import { cacheRoute } from '../middlewares/cache'
+import { cacheRouteFactory } from '../middlewares/cache/cache'
import { VideoModel } from '../models/video/video'
import { VideoCommentModel } from '../models/video/video-comment'
const feedsRouter = express.Router()
+const cacheRoute = cacheRouteFactory({
+ headerBlacklist: [ 'Content-Type' ]
+})
+
feedsRouter.get('/feeds/video-comments.:format',
feedsFormatValidator,
setFeedFormatContentType,
- asyncMiddleware(cacheRoute({
- headerBlacklist: [
- 'Content-Type'
- ]
- })(ROUTE_CACHE_LIFETIME.FEEDS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.FEEDS),
asyncMiddleware(videoFeedsValidator),
asyncMiddleware(videoCommentsFeedsValidator),
asyncMiddleware(generateVideoCommentsFeed)
setDefaultVideosSort,
feedsFormatValidator,
setFeedFormatContentType,
- asyncMiddleware(cacheRoute({
- headerBlacklist: [
- 'Content-Type'
- ]
- })(ROUTE_CACHE_LIFETIME.FEEDS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.FEEDS),
commonVideosFiltersValidator,
asyncMiddleware(videoFeedsValidator),
asyncMiddleware(generateVideoFeed)
setDefaultVideosSort,
feedsFormatValidator,
setFeedFormatContentType,
- asyncMiddleware(cacheRoute({
- headerBlacklist: [
- 'Content-Type'
- ]
- })(ROUTE_CACHE_LIFETIME.FEEDS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.FEEDS),
commonVideosFiltersValidator,
asyncMiddleware(videoSubscriptionFeedsValidator),
asyncMiddleware(generateVideoFeedForSubscriptions)
feed.addItem({
title: video.name,
id: video.url,
- link: WEBSERVER.URL + '/w/' + video.uuid,
+ link: WEBSERVER.URL + video.getWatchStaticPath(),
description: video.getTruncatedDescription(),
content: video.description,
author: [
import * as cors from 'cors'
import * as express from 'express'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants'
import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache'
import * as express from 'express'
import { mapToJSON } from '@server/helpers/core-utils'
import { LiveSegmentShaStore } from '@server/lib/live'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
const liveRouter = express.Router()
import { logger } from '@server/helpers/logger'
import { optionalAuthenticate } from '@server/middlewares/auth'
import { getCompleteLocale, is18nLocale } from '../../shared/core-utils/i18n'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { PluginType } from '../../shared/models/plugins/plugin.type'
import { isTestInstance } from '../helpers/core-utils'
import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants'
import { join } from 'path'
import { serveIndexHTML } from '@server/lib/client-html'
import { ServerConfigManager } from '@server/lib/server-config-manager'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model'
import { root } from '../helpers/core-utils'
import { CONFIG, isEmailEnabled } from '../initializers/config'
} from '../initializers/constants'
import { getThemeOrDefault } from '../lib/plugins/theme-utils'
import { asyncMiddleware } from '../middlewares'
-import { cacheRoute } from '../middlewares/cache'
+import { cacheRoute } from '../middlewares/cache/cache'
import { UserModel } from '../models/user/user'
import { VideoModel } from '../models/video/video'
import { VideoCommentModel } from '../models/video/video-comment'
// robots.txt service
staticRouter.get('/robots.txt',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.ROBOTS)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.ROBOTS),
(_, res: express.Response) => {
res.type('text/plain')
return res.send(CONFIG.INSTANCE.ROBOTS)
)
staticRouter.get('/.well-known/security.txt',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.SECURITYTXT)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.SECURITYTXT),
(_, res: express.Response) => {
res.type('text/plain')
return res.send(CONFIG.INSTANCE.SECURITYTXT + CONFIG.INSTANCE.SECURITYTXT_CONTACT)
// nodeinfo service
staticRouter.use('/.well-known/nodeinfo',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.NODEINFO)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO),
(_, res: express.Response) => {
return res.json({
links: [
}
)
staticRouter.use('/nodeinfo/:version.json',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.NODEINFO)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO),
asyncMiddleware(generateNodeinfo)
)
// dnt-policy.txt service (see https://www.eff.org/dnt-policy)
staticRouter.use('/.well-known/dnt-policy.txt',
- asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.DNT_POLICY)),
+ cacheRoute(ROUTE_CACHE_LIFETIME.DNT_POLICY),
(_, res: express.Response) => {
res.type('text/plain')
-import { exists } from './misc'
+import { exists, isArray } from './misc'
import { FollowState } from '@shared/models'
function isFollowStateValid (value: FollowState) {
return value === 'pending' || value === 'accepted'
}
+function isRemoteHandleValid (value: string) {
+ if (!exists(value)) return false
+ if (typeof value !== 'string') return false
+
+ return value.includes('@')
+}
+
+function isEachUniqueHandleValid (handles: string[]) {
+ return isArray(handles) &&
+ handles.every(handle => {
+ return isRemoteHandleValid(handle) && handles.indexOf(handle) === handles.lastIndexOf(handle)
+ })
+}
+
// ---------------------------------------------------------------------------
export {
- isFollowStateValid
+ isFollowStateValid,
+ isRemoteHandleValid,
+ isEachUniqueHandleValid
}
return Array.isArray(value) && value.every(v => validator.isInt('' + v)) && value.length !== 0
}
+function isNotEmptyStringArray (value: any) {
+ return Array.isArray(value) && value.every(v => typeof v === 'string' && v.length !== 0) && value.length !== 0
+}
+
function isArrayOf (value: any, validator: (value: any) => boolean) {
return isArray(value) && value.every(v => validator(v))
}
return exists(value) && validator.isUUID('' + value, 4)
}
+function areUUIDsValid (values: string[]) {
+ return isArray(values) && values.every(v => isUUIDValid(v))
+}
+
function isIdOrUUIDValid (value: string) {
return isIdValid(value) || isUUIDValid(value)
}
return value
}
+function toCompleteUUIDs (values: string[]) {
+ return values.map(v => toCompleteUUID(v))
+}
+
function toIntOrNull (value: string) {
const v = toValueOrNull(value)
isIntOrNull,
isIdValid,
isSafePath,
+ isNotEmptyStringArray,
isUUIDValid,
+ toCompleteUUIDs,
toCompleteUUID,
isIdOrUUIDValid,
isDateValid,
toBooleanOrNull,
isBooleanValid,
toIntOrNull,
+ areUUIDsValid,
toArray,
toIntArray,
isFileFieldValid,
function isEachUniqueHostValid (hosts: string[]) {
return isArray(hosts) &&
- hosts.length !== 0 &&
hosts.every(host => {
return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host)
})
import { Response } from 'express'
import { MUserId } from '@server/types/models'
import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) {
if (videoChangeOwnership.NextOwner.userId === user.id) {
import * as retry from 'async/retry'
import * as Bluebird from 'bluebird'
-import { QueryTypes, Transaction } from 'sequelize'
+import { Transaction } from 'sequelize'
import { Model } from 'sequelize-typescript'
import { sequelizeTypescript } from '@server/initializers/database'
import { logger } from './logger'
function retryTransactionWrapper <T, A, B, C, D> (
- functionToRetry: (arg1: A, arg2: B, arg3: C, arg4: D) => Promise<T> | Bluebird<T>,
+ functionToRetry: (arg1: A, arg2: B, arg3: C, arg4: D) => Promise<T>,
arg1: A,
arg2: B,
arg3: C,
): Promise<T>
function retryTransactionWrapper <T, A, B, C> (
- functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise<T> | Bluebird<T>,
+ functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise<T>,
arg1: A,
arg2: B,
arg3: C
): Promise<T>
function retryTransactionWrapper <T, A, B> (
- functionToRetry: (arg1: A, arg2: B) => Promise<T> | Bluebird<T>,
+ functionToRetry: (arg1: A, arg2: B) => Promise<T>,
arg1: A,
arg2: B
): Promise<T>
function retryTransactionWrapper <T, A> (
- functionToRetry: (arg1: A) => Promise<T> | Bluebird<T>,
+ functionToRetry: (arg1: A) => Promise<T>,
arg1: A
): Promise<T>
): Promise<T>
function retryTransactionWrapper <T> (
- functionToRetry: (...args: any[]) => Promise<T> | Bluebird<T>,
+ functionToRetry: (...args: any[]) => Promise<T>,
...args: any[]
): Promise<T> {
return transactionRetryer<T>(callback => {
})
}
-function deleteNonExistingModels <T extends { hasSameUniqueKeysThan (other: T): boolean } & Pick<Model, 'destroy'>> (
+function filterNonExistingModels <T extends { hasSameUniqueKeysThan (other: T): boolean }> (
fromDatabase: T[],
- newModels: T[],
- t: Transaction
+ newModels: T[]
) {
return fromDatabase.filter(f => !newModels.find(newModel => newModel.hasSameUniqueKeysThan(f)))
- .map(f => f.destroy({ transaction: t }))
}
-// Sequelize always skip the update if we only update updatedAt field
-function setAsUpdated (table: string, id: number, transaction?: Transaction) {
- return sequelizeTypescript.query(
- `UPDATE "${table}" SET "updatedAt" = :updatedAt WHERE id = :id`,
- {
- replacements: { table, id, updatedAt: new Date() },
- type: QueryTypes.UPDATE,
- transaction
- }
- )
+function deleteAllModels <T extends Pick<Model, 'destroy'>> (models: T[], transaction: Transaction) {
+ return Promise.all(models.map(f => f.destroy({ transaction })))
}
// ---------------------------------------------------------------------------
transactionRetryer,
updateInstanceWithAnother,
afterCommitIfTransaction,
- deleteNonExistingModels,
- setAsUpdated,
+ filterNonExistingModels,
+ deleteAllModels,
runInReadCommittedTransaction
}
import * as express from 'express'
import * as multer from 'multer'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { CONFIG } from '../initializers/config'
import { REMOTE_SCHEME } from '../initializers/constants'
import { getLowercaseExtension } from './core-utils'
async function getLiveTranscodingCommand (options: {
rtmpUrl: string
+
outPath: string
+ masterPlaylistName: string
+
resolutions: number[]
fps: number
availableEncoders: AvailableEncoders
profile: string
}) {
- const { rtmpUrl, outPath, resolutions, fps, availableEncoders, profile } = options
+ const { rtmpUrl, outPath, resolutions, fps, availableEncoders, profile, masterPlaylistName } = options
const input = rtmpUrl
const command = getFFmpeg(input, 'live')
command.complexFilter(complexFilter)
- addDefaultLiveHLSParams(command, outPath)
+ addDefaultLiveHLSParams(command, outPath, masterPlaylistName)
command.outputOption('-var_stream_map', varStreamMap.join(' '))
return command
}
-function getLiveMuxingCommand (rtmpUrl: string, outPath: string) {
+function getLiveMuxingCommand (rtmpUrl: string, outPath: string, masterPlaylistName: string) {
const command = getFFmpeg(rtmpUrl, 'live')
command.outputOption('-c:v copy')
command.outputOption('-map 0:a?')
command.outputOption('-map 0:v?')
- addDefaultLiveHLSParams(command, outPath)
+ addDefaultLiveHLSParams(command, outPath, masterPlaylistName)
return command
}
}
}
-function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string) {
+function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string, masterPlaylistName: string) {
command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME_SECONDS)
command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE)
command.outputOption('-hls_flags delete_segments+independent_segments')
command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%06d.ts')}`)
- command.outputOption('-master_pl_name master.m3u8')
+ command.outputOption('-master_pl_name ' + masterPlaylistName)
command.outputOption(`-f hls`)
command.output(join(outPath, '%v.m3u8'))
const { command, silent = false, job } = options
return new Promise<void>((res, rej) => {
+ let shellCommand: string
+
+ command.on('start', cmdline => { shellCommand = cmdline })
+
command.on('error', (err, stdout, stderr) => {
if (silent !== true) logger.error('Error in ffmpeg.', { stdout, stderr })
})
command.on('end', (stdout, stderr) => {
- logger.debug('FFmpeg command ended.', { stdout, stderr })
+ logger.debug('FFmpeg command ended.', { stdout, stderr, shellCommand })
res()
})
// Thanks http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
-import { mkdirpSync } from 'fs-extra'
+import { mkdirpSync, stat } from 'fs-extra'
import { omit } from 'lodash'
import * as path from 'path'
import { format as sqlFormat } from 'sql-formatter'
}
}
+async function mtimeSortFilesDesc (files: string[], basePath: string) {
+ const promises = []
+ const out: { file: string, mtime: number }[] = []
+
+ for (const file of files) {
+ const p = stat(basePath + '/' + file)
+ .then(stats => {
+ if (stats.isFile()) out.push({ file, mtime: stats.mtime.getTime() })
+ })
+
+ promises.push(p)
+ }
+
+ await Promise.all(promises)
+
+ out.sort((a, b) => b.mtime - a.mtime)
+
+ return out
+}
+
// ---------------------------------------------------------------------------
export {
labelFormatter,
consoleLoggerFormat,
jsonLoggerFormat,
+ mtimeSortFilesDesc,
logger,
loggerTagsFactory,
bunyanLogger
--- /dev/null
+import { pick } from '@shared/core-utils'
+import {
+ VideoChannelsSearchQueryAfterSanitize,
+ VideoPlaylistsSearchQueryAfterSanitize,
+ VideosCommonQueryAfterSanitize,
+ VideosSearchQueryAfterSanitize
+} from '@shared/models'
+
+function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
+ return pick(query, [
+ 'start',
+ 'count',
+ 'sort',
+ 'nsfw',
+ 'isLive',
+ 'categoryOneOf',
+ 'licenceOneOf',
+ 'languageOneOf',
+ 'tagsOneOf',
+ 'tagsAllOf',
+ 'filter',
+ 'skipCount'
+ ])
+}
+
+function pickSearchVideoQuery (query: VideosSearchQueryAfterSanitize) {
+ return {
+ ...pickCommonVideoQuery(query),
+
+ ...pick(query, [
+ 'searchTarget',
+ 'search',
+ 'host',
+ 'startDate',
+ 'endDate',
+ 'originallyPublishedStartDate',
+ 'originallyPublishedEndDate',
+ 'durationMin',
+ 'durationMax',
+ 'uuids'
+ ])
+ }
+}
+
+function pickSearchChannelQuery (query: VideoChannelsSearchQueryAfterSanitize) {
+ return pick(query, [
+ 'searchTarget',
+ 'search',
+ 'start',
+ 'count',
+ 'sort',
+ 'host',
+ 'handles'
+ ])
+}
+
+function pickSearchPlaylistQuery (query: VideoPlaylistsSearchQueryAfterSanitize) {
+ return pick(query, [
+ 'searchTarget',
+ 'search',
+ 'start',
+ 'count',
+ 'sort',
+ 'host',
+ 'uuids'
+ ])
+}
+
+export {
+ pickCommonVideoQuery,
+ pickSearchVideoQuery,
+ pickSearchPlaylistQuery,
+ pickSearchChannelQuery
+}
await writeFile(torrentPath, torrent)
+ // Remove old torrent file if it existed
+ if (videoFile.hasTorrent()) {
+ await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename))
+ }
+
const parsedTorrent = parseTorrent(torrent)
videoFile.infoHash = parsedTorrent.infoHash
videoFile.torrentFilename = torrentFilename
import got from 'got'
import { join } from 'path'
import { CONFIG } from '@server/initializers/config'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { VideoResolution } from '../../shared/models/videos'
import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../initializers/constants'
import { peertubeTruncate, pipelinePromise, root } from './core-utils'
import { randomBytes } from 'crypto'
import { invert } from 'lodash'
import { join } from 'path'
-import { randomInt } from '../../shared/core-utils/miscs/miscs'
+import { randomInt } from '../../shared/core-utils/common/miscs'
import {
AbuseState,
JobType,
// ---------------------------------------------------------------------------
-const LAST_MIGRATION_VERSION = 650
+const LAST_MIGRATION_VERSION = 655
// ---------------------------------------------------------------------------
--- /dev/null
+import * as Sequelize from 'sequelize'
+
+async function up (utils: {
+ transaction: Sequelize.Transaction
+ queryInterface: Sequelize.QueryInterface
+ sequelize: Sequelize.Sequelize
+ db: any
+}): Promise<void> {
+ {
+ for (const column of [ 'playlistUrl', 'segmentsSha256Url' ]) {
+ const data = {
+ type: Sequelize.STRING,
+ allowNull: true,
+ defaultValue: null
+ }
+
+ await utils.queryInterface.changeColumn('videoStreamingPlaylist', column, data)
+ }
+ }
+
+ {
+ await utils.sequelize.query(
+ `UPDATE "videoStreamingPlaylist" SET "playlistUrl" = NULL, "segmentsSha256Url" = NULL ` +
+ `WHERE "videoId" IN (SELECT id FROM video WHERE remote IS FALSE)`
+ )
+ }
+
+ {
+ for (const column of [ 'playlistFilename', 'segmentsSha256Filename' ]) {
+ const data = {
+ type: Sequelize.STRING,
+ allowNull: true,
+ defaultValue: null
+ }
+
+ await utils.queryInterface.addColumn('videoStreamingPlaylist', column, data)
+ }
+ }
+
+ {
+ await utils.sequelize.query(
+ `UPDATE "videoStreamingPlaylist" SET "playlistFilename" = 'master.m3u8', "segmentsSha256Filename" = 'segments-sha256.json'`
+ )
+ }
+
+ {
+ for (const column of [ 'playlistFilename', 'segmentsSha256Filename' ]) {
+ const data = {
+ type: Sequelize.STRING,
+ allowNull: false,
+ defaultValue: null
+ }
+
+ await utils.queryInterface.changeColumn('videoStreamingPlaylist', column, data)
+ }
+ }
+}
+
+function down (options) {
+ throw new Error('Not implemented.')
+}
+
+export {
+ up,
+ down
+}
import { ActorLoadByUrlType } from '@server/lib/model-loaders'
import { ActorModel } from '@server/models/actor/actor'
import { MActorAccountChannelId, MActorFull } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
import { fetchRemoteActor } from './shared'
import { APActorUpdater } from './updater'
import { getUrlFromWebfinger } from './webfinger'
+import { retryTransactionWrapper } from '@server/helpers/database-utils'
import * as Bluebird from 'bluebird'
import { URL } from 'url'
import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub'
}
}
- if (cleaner) await cleaner(startDate)
+ if (cleaner) await retryTransactionWrapper(cleaner, startDate)
}
export {
}
}
+// If we only have an host, use a default account handle
+function getRemoteNameAndHost (handleOrHost: string) {
+ let name = SERVER_ACTOR_NAME
+ let host = handleOrHost
+
+ const splitted = handleOrHost.split('@')
+ if (splitted.length === 2) {
+ name = splitted[0]
+ host = splitted[1]
+ }
+
+ return { name, host }
+}
+
export {
- autoFollowBackIfNeeded
+ autoFollowBackIfNeeded,
+ getRemoteNameAndHost
}
import { PeerTubeRequestError } from '@server/helpers/requests'
import { JobQueue } from '@server/lib/job-queue'
import { MVideoPlaylist, MVideoPlaylistOwner } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
import { createOrUpdateVideoPlaylist } from './create-update'
import { fetchRemoteVideoPlaylist } from './shared'
import { VideoLoadByUrlType } from '@server/lib/model-loaders'
import { VideoModel } from '@server/models/video/video'
import { MVideoAccountLightBlacklistAllFiles, MVideoThumbnail } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
import { fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared'
import { APVideoUpdater } from './updater'
import { Transaction } from 'sequelize/types'
import { checkUrlsSameHost } from '@server/helpers/activitypub'
-import { deleteNonExistingModels } from '@server/helpers/database-utils'
+import { deleteAllModels, filterNonExistingModels } from '@server/helpers/database-utils'
import { logger, LoggerTagsFn } from '@server/helpers/logger'
import { updatePlaceholderThumbnail, updateVideoMiniatureFromUrl } from '@server/lib/thumbnail'
import { setVideoTags } from '@server/lib/video'
const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))
// Remove video files that do not exist anymore
- const destroyTasks = deleteNonExistingModels(video.VideoFiles || [], newVideoFiles, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(video.VideoFiles || [], newVideoFiles), t)
// Update or add other one
const upsertTasks = newVideoFiles.map(f => VideoFileModel.customUpsert(f, 'video', t))
const newStreamingPlaylists = streamingPlaylistAttributes.map(a => new VideoStreamingPlaylistModel(a))
// Remove video playlists that do not exist anymore
- const destroyTasks = deleteNonExistingModels(video.VideoStreamingPlaylists || [], newStreamingPlaylists, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(video.VideoStreamingPlaylists || [], newStreamingPlaylists), t)
video.VideoStreamingPlaylists = []
for (const playlistAttributes of streamingPlaylistAttributes) {
-
const streamingPlaylistModel = await this.insertOrReplaceStreamingPlaylist(playlistAttributes, t)
streamingPlaylistModel.Video = video
const newVideoFiles: MVideoFile[] = getFileAttributesFromUrl(playlistModel, tagObjects).map(a => new VideoFileModel(a))
- const destroyTasks = deleteNonExistingModels(oldStreamingPlaylistFiles, newVideoFiles, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(oldStreamingPlaylistFiles, newVideoFiles), t)
// Update or add other one
const upsertTasks = newVideoFiles.map(f => VideoFileModel.customUpsert(f, 'streaming-playlist', t))
import { getExtFromMimetype } from '@server/helpers/video'
import { ACTIVITY_PUB, MIMETYPES, P2P_MEDIA_LOADER_PEER_VERSION, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '@server/initializers/constants'
import { generateTorrentFileName } from '@server/lib/video-paths'
+import { VideoCaptionModel } from '@server/models/video/video-caption'
import { VideoFileModel } from '@server/models/video/video-file'
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
import { FilteredModelAttributes } from '@server/types'
-import { MChannelId, MStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoId } from '@server/types/models'
+import { isStreamingPlaylist, MChannelId, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoId } from '@server/types/models'
import {
ActivityHashTagObject,
ActivityMagnetUrlObject,
VideoPrivacy,
VideoStreamingPlaylistType
} from '@shared/models'
-import { VideoCaptionModel } from '@server/models/video/video-caption'
function getThumbnailFromIcons (videoObject: VideoObject) {
let validIcons = videoObject.icon.filter(i => i.width > THUMBNAILS_SIZE.minWidth)
const extname = getExtFromMimetype(MIMETYPES.VIDEO.MIMETYPE_EXT, fileUrl.mediaType)
const resolution = fileUrl.height
- const videoId = (videoOrPlaylist as MStreamingPlaylist).playlistUrl ? null : videoOrPlaylist.id
- const videoStreamingPlaylistId = (videoOrPlaylist as MStreamingPlaylist).playlistUrl ? videoOrPlaylist.id : null
+ const videoId = isStreamingPlaylist(videoOrPlaylist) ? null : videoOrPlaylist.id
+ const videoStreamingPlaylistId = isStreamingPlaylist(videoOrPlaylist) ? videoOrPlaylist.id : null
const attribute = {
extname,
const attribute = {
type: VideoStreamingPlaylistType.HLS,
+
+ playlistFilename: basename(playlistUrlObject.href),
playlistUrl: playlistUrlObject.href,
+
+ segmentsSha256Filename: basename(segmentsSha256UrlObject.href),
segmentsSha256Url: segmentsSha256UrlObject.href,
+
p2pMediaLoaderInfohashes: VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(playlistUrlObject.href, files),
p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
videoId: video.id,
import { escapeHTML } from '@shared/core-utils/renderer'
import { HTMLServerConfig } from '@shared/models'
import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
import { isTestInstance, sha256 } from '../helpers/core-utils'
import { logger } from '../helpers/logger'
let customHtml = ClientHtml.addTitleTag(html, escapeHTML(videoPlaylist.name))
customHtml = ClientHtml.addDescriptionTag(customHtml, mdToPlainText(videoPlaylist.description))
- const url = videoPlaylist.getWatchUrl()
+ const url = WEBSERVER.URL + videoPlaylist.getWatchStaticPath()
const originUrl = videoPlaylist.url
const title = escapeHTML(videoPlaylist.name)
const siteName = escapeHTML(CONFIG.INSTANCE.NAME)
import { close, ensureDir, move, open, outputJSON, pathExists, read, readFile, remove, writeFile } from 'fs-extra'
import { flatten, uniq } from 'lodash'
import { basename, dirname, join } from 'path'
-import { MVideoWithFile } from '@server/types/models'
+import { MStreamingPlaylistFilesVideo, MVideoWithFile } from '@server/types/models'
import { sha256 } from '../helpers/core-utils'
import { getAudioStreamCodec, getVideoStreamCodec, getVideoStreamSize } from '../helpers/ffprobe-utils'
import { logger } from '../helpers/logger'
import { sequelizeTypescript } from '../initializers/database'
import { VideoFileModel } from '../models/video/video-file'
import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
-import { getVideoFilePath } from './video-paths'
+import { getHlsResolutionPlaylistFilename, getVideoFilePath } from './video-paths'
async function updateStreamingPlaylistsInfohashesIfNeeded () {
const playlistsToUpdate = await VideoStreamingPlaylistModel.listByIncorrectPeerVersion()
await sequelizeTypescript.transaction(async t => {
const videoFiles = await VideoFileModel.listByStreamingPlaylist(playlist.id, t)
- playlist.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(playlist.playlistUrl, videoFiles)
+ playlist.assignP2PMediaLoaderInfoHashes(playlist.Video, videoFiles)
playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION
+
await playlist.save({ transaction: t })
})
}
}
-async function updateMasterHLSPlaylist (video: MVideoWithFile) {
+async function updateMasterHLSPlaylist (video: MVideoWithFile, playlist: MStreamingPlaylistFilesVideo) {
const directory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
+
const masterPlaylists: string[] = [ '#EXTM3U', '#EXT-X-VERSION:3' ]
- const masterPlaylistPath = join(directory, VideoStreamingPlaylistModel.getMasterHlsPlaylistFilename())
- const streamingPlaylist = video.getHLSPlaylist()
- for (const file of streamingPlaylist.VideoFiles) {
+ const masterPlaylistPath = join(directory, playlist.playlistFilename)
+
+ for (const file of playlist.VideoFiles) {
+ const playlistFilename = getHlsResolutionPlaylistFilename(file.filename)
+
// If we did not generated a playlist for this resolution, skip
- const filePlaylistPath = join(directory, VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution))
+ const filePlaylistPath = join(directory, playlistFilename)
if (await pathExists(filePlaylistPath) === false) continue
- const videoFilePath = getVideoFilePath(streamingPlaylist, file)
+ const videoFilePath = getVideoFilePath(playlist, file)
const size = await getVideoStreamSize(videoFilePath)
line += `,CODECS="${codecs.filter(c => !!c).join(',')}"`
masterPlaylists.push(line)
- masterPlaylists.push(VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution))
+ masterPlaylists.push(playlistFilename)
}
await writeFile(masterPlaylistPath, masterPlaylists.join('\n') + '\n')
}
-async function updateSha256VODSegments (video: MVideoWithFile) {
+async function updateSha256VODSegments (video: MVideoWithFile, playlist: MStreamingPlaylistFilesVideo) {
const json: { [filename: string]: { [range: string]: string } } = {}
const playlistDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
- const hlsPlaylist = video.getHLSPlaylist()
// For all the resolutions available for this video
- for (const file of hlsPlaylist.VideoFiles) {
+ for (const file of playlist.VideoFiles) {
const rangeHashes: { [range: string]: string } = {}
- const videoPath = getVideoFilePath(hlsPlaylist, file)
- const playlistPath = join(playlistDirectory, VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution))
+ const videoPath = getVideoFilePath(playlist, file)
+ const resolutionPlaylistPath = join(playlistDirectory, getHlsResolutionPlaylistFilename(file.filename))
// Maybe the playlist is not generated for this resolution yet
- if (!await pathExists(playlistPath)) continue
+ if (!await pathExists(resolutionPlaylistPath)) continue
- const playlistContent = await readFile(playlistPath)
+ const playlistContent = await readFile(resolutionPlaylistPath)
const ranges = getRangesFromPlaylist(playlistContent.toString())
const fd = await open(videoPath, 'r')
json[videoFilename] = rangeHashes
}
- const outputPath = join(playlistDirectory, VideoStreamingPlaylistModel.getHlsSha256SegmentsFilename())
+ const outputPath = join(playlistDirectory, playlist.segmentsSha256Filename)
await outputJSON(outputPath, json)
}
import { VideoModel } from '@server/models/video/video'
import { VideoCommentModel } from '@server/models/video/video-comment'
import { VideoShareModel } from '@server/models/video/video-share'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
import { copy, stat } from 'fs-extra'
import { getLowercaseExtension } from '@server/helpers/core-utils'
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
-import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
+import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
import { UserModel } from '@server/models/user/user'
import { MVideoFullLight } from '@server/types/models'
import { VideoFileImportPayload } from '@shared/models'
if (currentVideoFile) {
// Remove old file and old torrent
- await video.removeFile(currentVideoFile)
- await currentVideoFile.removeTorrent()
+ await video.removeFileAndTorrent(currentVideoFile)
// Remove the old video file from the array
video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile)
const newVideoFile = new VideoFileModel({
resolution: videoFileResolution,
extname: fileExt,
- filename: generateVideoFilename(video, false, videoFileResolution, fileExt),
+ filename: generateWebTorrentVideoFilename(videoFileResolution, fileExt),
size,
fps,
videoId: video.id
import { ServerConfigManager } from '@server/lib/server-config-manager'
import { isAbleToUploadVideo } from '@server/lib/user'
import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
-import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
+import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
import { ThumbnailModel } from '@server/models/video/thumbnail'
import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/types/models/video/video-import'
import {
extname: fileExt,
resolution: videoFileResolution,
size: stats.size,
- filename: generateVideoFilename(videoImport.Video, false, videoFileResolution, fileExt),
+ filename: generateWebTorrentVideoFilename(videoFileResolution, fileExt),
fps,
videoId: videoImport.videoId
}
import { generateVideoMiniature } from '@server/lib/thumbnail'
import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/video-transcoding'
import { publishAndFederateIfNeeded } from '@server/lib/video'
-import { getHLSDirectory } from '@server/lib/video-paths'
+import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename, getHLSDirectory } from '@server/lib/video-paths'
import { VideoModel } from '@server/models/video/video'
import { VideoFileModel } from '@server/models/video/video-file'
import { VideoLiveModel } from '@server/models/video/video-live'
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
-import { MVideo, MVideoLive } from '@server/types/models'
+import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models'
import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
import { logger } from '../../../helpers/logger'
return cleanupLive(video, streamingPlaylist)
}
- return saveLive(video, live)
+ return saveLive(video, live, streamingPlaylist)
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
-async function saveLive (video: MVideo, live: MVideoLive) {
+async function saveLive (video: MVideo, live: MVideoLive, streamingPlaylist: MStreamingPlaylist) {
const hlsDirectory = getHLSDirectory(video, false)
const replayDirectory = join(hlsDirectory, VIDEO_LIVE.REPLAY_DIRECTORY)
const rootFiles = await readdir(hlsDirectory)
const playlistFiles = rootFiles.filter(file => {
- return file.endsWith('.m3u8') && file !== 'master.m3u8'
+ return file.endsWith('.m3u8') && file !== streamingPlaylist.playlistFilename
})
await cleanupLiveFiles(hlsDirectory)
const hlsPlaylist = videoWithFiles.getHLSPlaylist()
await VideoFileModel.removeHLSFilesOfVideoId(hlsPlaylist.id)
+
+ // Reset playlist
hlsPlaylist.VideoFiles = []
+ hlsPlaylist.playlistFilename = generateHLSMasterPlaylistFilename()
+ hlsPlaylist.segmentsSha256Filename = generateHlsSha256SegmentsFilename()
+ await hlsPlaylist.save()
let durationDone = false
if (payload.isMaxQuality && CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false) {
// Remove webtorrent files if not enabled
for (const file of video.VideoFiles) {
- await video.removeFile(file)
- await file.removeTorrent()
+ await video.removeFileAndTorrent(file)
await file.destroy()
}
import { computeResolutionsToTranscode, getVideoFileFPS, getVideoFileResolution } from '@server/helpers/ffprobe-utils'
import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config'
-import { P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME, WEBSERVER } from '@server/initializers/constants'
+import { P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME } from '@server/initializers/constants'
import { UserModel } from '@server/models/user/user'
import { VideoModel } from '@server/models/video/video'
import { VideoLiveModel } from '@server/models/video/video-live'
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
-import { MStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoLiveVideo } from '@server/types/models'
+import { MStreamingPlaylistVideo, MVideo, MVideoLiveVideo } from '@server/types/models'
import { VideoState, VideoStreamingPlaylistType } from '@shared/models'
import { federateVideoIfNeeded } from '../activitypub/videos'
import { JobQueue } from '../job-queue'
import { PeerTubeSocket } from '../peertube-socket'
+import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename } from '../video-paths'
import { LiveQuotaStore } from './live-quota-store'
import { LiveSegmentShaStore } from './live-segment-sha-store'
import { cleanupLive } from './live-utils'
import { MuxingSession } from './shared'
-const NodeRtmpSession = require('node-media-server/node_rtmp_session')
-const context = require('node-media-server/node_core_ctx')
-const nodeMediaServerLogger = require('node-media-server/node_core_logger')
+const NodeRtmpSession = require('node-media-server/src/node_rtmp_session')
+const context = require('node-media-server/src/node_core_ctx')
+const nodeMediaServerLogger = require('node-media-server/src/node_core_logger')
// Disable node media server logs
nodeMediaServerLogger.setLogType(0)
return resolutionsEnabled.concat([ originResolution ])
}
- private async createLivePlaylist (video: MVideo, allResolutions: number[]) {
- const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
- const [ videoStreamingPlaylist ] = await VideoStreamingPlaylistModel.upsert({
- videoId: video.id,
- playlistUrl,
- segmentsSha256Url: WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid, video.isLive),
- p2pMediaLoaderInfohashes: VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(playlistUrl, allResolutions),
- p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
+ private async createLivePlaylist (video: MVideo, allResolutions: number[]): Promise<MStreamingPlaylistVideo> {
+ const playlist = await VideoStreamingPlaylistModel.loadOrGenerate(video)
- type: VideoStreamingPlaylistType.HLS
- }, { returning: true }) as [ MStreamingPlaylist, boolean ]
+ playlist.playlistFilename = generateHLSMasterPlaylistFilename(true)
+ playlist.segmentsSha256Filename = generateHlsSha256SegmentsFilename(true)
- return Object.assign(videoStreamingPlaylist, { Video: video })
+ playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION
+ playlist.type = VideoStreamingPlaylistType.HLS
+
+ playlist.assignP2PMediaLoaderInfoHashes(video, allResolutions)
+
+ return playlist.save()
}
static get Instance () {
this.ffmpegCommand = CONFIG.LIVE.TRANSCODING.ENABLED
? await getLiveTranscodingCommand({
rtmpUrl: this.rtmpUrl,
+
outPath,
+ masterPlaylistName: this.streamingPlaylist.playlistFilename,
+
resolutions: this.allResolutions,
fps: this.fps,
availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
profile: CONFIG.LIVE.TRANSCODING.PROFILE
})
- : getLiveMuxingCommand(this.rtmpUrl, outPath)
+ : getLiveMuxingCommand(this.rtmpUrl, outPath, this.streamingPlaylist.playlistFilename)
logger.info('Running live muxing/transcoding for %s.', this.videoUUID, this.lTags)
}
private watchMasterFile (outPath: string) {
- this.masterWatcher = chokidar.watch(outPath + '/master.m3u8')
+ this.masterWatcher = chokidar.watch(outPath + '/' + this.streamingPlaylist.playlistFilename)
this.masterWatcher.on('add', async () => {
this.emit('master-playlist-created', { videoId: this.videoId })
import { VideoObject } from '../../shared/models/activitypub/objects'
import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
-import { VideoCommentCreate } from '../../shared/models/videos/comment/video-comment.model'
+import { VideoCommentCreate } from '../../shared/models/videos/comment'
import { ActorModel } from '../models/actor/actor'
import { UserModel } from '../models/user/user'
import { VideoModel } from '../models/video/video'
import * as express from 'express'
import { logger } from '@server/helpers/logger'
-import {
- VIDEO_CATEGORIES,
- VIDEO_LANGUAGES,
- VIDEO_LICENCES,
- VIDEO_PLAYLIST_PRIVACIES,
- VIDEO_PRIVACIES
-} from '@server/initializers/constants'
import { onExternalUserAuthenticated } from '@server/lib/auth/external-auth'
+import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
import { PluginModel } from '@server/models/server/plugin'
import {
RegisterServerAuthExternalOptions,
} from '@server/types/plugins'
import {
EncoderOptionsBuilder,
- PluginPlaylistPrivacyManager,
PluginSettingsManager,
PluginStorageManager,
- PluginVideoCategoryManager,
- PluginVideoLanguageManager,
- PluginVideoLicenceManager,
- PluginVideoPrivacyManager,
RegisterServerHookOptions,
RegisterServerSettingOptions,
- serverHookObject
+ serverHookObject,
+ VideoPlaylistPrivacy,
+ VideoPrivacy
} from '@shared/models'
import { VideoTranscodingProfilesManager } from '../transcoding/video-transcoding-profiles'
import { buildPluginHelpers } from './plugin-helpers-builder'
-type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy'
-type VideoConstant = { [key in number | string]: string }
-
-type UpdatedVideoConstant = {
- [name in AlterableVideoConstant]: {
- [ npmName: string]: {
- added: { key: number | string, label: string }[]
- deleted: { key: number | string, label: string }[]
- }
- }
-}
-
export class RegisterHelpers {
- private readonly updatedVideoConstants: UpdatedVideoConstant = {
- playlistPrivacy: { },
- privacy: { },
- language: { },
- licence: { },
- category: { }
- }
-
private readonly transcodingProfiles: {
[ npmName: string ]: {
type: 'vod' | 'live'
private readonly onSettingsChangeCallbacks: ((settings: any) => Promise<any>)[] = []
private readonly router: express.Router
+ private readonly videoConstantManagerFactory: VideoConstantManagerFactory
constructor (
private readonly npmName: string,
private readonly onHookAdded: (options: RegisterServerHookOptions) => void
) {
this.router = express.Router()
+ this.videoConstantManagerFactory = new VideoConstantManagerFactory(this.npmName)
}
buildRegisterHelpers (): RegisterServerOptions {
const settingsManager = this.buildSettingsManager()
const storageManager = this.buildStorageManager()
- const videoLanguageManager = this.buildVideoLanguageManager()
+ const videoLanguageManager = this.videoConstantManagerFactory.createVideoConstantManager<string>('language')
- const videoLicenceManager = this.buildVideoLicenceManager()
- const videoCategoryManager = this.buildVideoCategoryManager()
+ const videoLicenceManager = this.videoConstantManagerFactory.createVideoConstantManager<number>('licence')
+ const videoCategoryManager = this.videoConstantManagerFactory.createVideoConstantManager<number>('category')
- const videoPrivacyManager = this.buildVideoPrivacyManager()
- const playlistPrivacyManager = this.buildPlaylistPrivacyManager()
+ const videoPrivacyManager = this.videoConstantManagerFactory.createVideoConstantManager<VideoPrivacy>('privacy')
+ const playlistPrivacyManager = this.videoConstantManagerFactory.createVideoConstantManager<VideoPlaylistPrivacy>('playlistPrivacy')
const transcodingManager = this.buildTranscodingManager()
settingsManager,
storageManager,
- videoLanguageManager,
- videoCategoryManager,
- videoLicenceManager,
+ videoLanguageManager: {
+ ...videoLanguageManager,
+ /** @deprecated use `addConstant` instead **/
+ addLanguage: videoLanguageManager.addConstant,
+ /** @deprecated use `deleteConstant` instead **/
+ deleteLanguage: videoLanguageManager.deleteConstant
+ },
+ videoCategoryManager: {
+ ...videoCategoryManager,
+ /** @deprecated use `addConstant` instead **/
+ addCategory: videoCategoryManager.addConstant,
+ /** @deprecated use `deleteConstant` instead **/
+ deleteCategory: videoCategoryManager.deleteConstant
+ },
+ videoLicenceManager: {
+ ...videoLicenceManager,
+ /** @deprecated use `addConstant` instead **/
+ addLicence: videoLicenceManager.addConstant,
+ /** @deprecated use `deleteConstant` instead **/
+ deleteLicence: videoLicenceManager.deleteConstant
+ },
- videoPrivacyManager,
- playlistPrivacyManager,
+ videoPrivacyManager: {
+ ...videoPrivacyManager,
+ /** @deprecated use `deleteConstant` instead **/
+ deletePrivacy: videoPrivacyManager.deleteConstant
+ },
+ playlistPrivacyManager: {
+ ...playlistPrivacyManager,
+ /** @deprecated use `deleteConstant` instead **/
+ deletePlaylistPrivacy: playlistPrivacyManager.deleteConstant
+ },
transcodingManager,
}
reinitVideoConstants (npmName: string) {
- const hash = {
- language: VIDEO_LANGUAGES,
- licence: VIDEO_LICENCES,
- category: VIDEO_CATEGORIES,
- privacy: VIDEO_PRIVACIES,
- playlistPrivacy: VIDEO_PLAYLIST_PRIVACIES
- }
- const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category', 'privacy', 'playlistPrivacy' ]
-
- for (const type of types) {
- const updatedConstants = this.updatedVideoConstants[type][npmName]
- if (!updatedConstants) continue
-
- for (const added of updatedConstants.added) {
- delete hash[type][added.key]
- }
-
- for (const deleted of updatedConstants.deleted) {
- hash[type][deleted.key] = deleted.label
- }
-
- delete this.updatedVideoConstants[type][npmName]
- }
+ this.videoConstantManagerFactory.resetVideoConstants(npmName)
}
reinitTranscodingProfilesAndEncoders (npmName: string) {
}
}
- private buildVideoLanguageManager (): PluginVideoLanguageManager {
- return {
- addLanguage: (key: string, label: string) => {
- return this.addConstant({ npmName: this.npmName, type: 'language', obj: VIDEO_LANGUAGES, key, label })
- },
-
- deleteLanguage: (key: string) => {
- return this.deleteConstant({ npmName: this.npmName, type: 'language', obj: VIDEO_LANGUAGES, key })
- }
- }
- }
-
- private buildVideoCategoryManager (): PluginVideoCategoryManager {
- return {
- addCategory: (key: number, label: string) => {
- return this.addConstant({ npmName: this.npmName, type: 'category', obj: VIDEO_CATEGORIES, key, label })
- },
-
- deleteCategory: (key: number) => {
- return this.deleteConstant({ npmName: this.npmName, type: 'category', obj: VIDEO_CATEGORIES, key })
- }
- }
- }
-
- private buildVideoPrivacyManager (): PluginVideoPrivacyManager {
- return {
- deletePrivacy: (key: number) => {
- return this.deleteConstant({ npmName: this.npmName, type: 'privacy', obj: VIDEO_PRIVACIES, key })
- }
- }
- }
-
- private buildPlaylistPrivacyManager (): PluginPlaylistPrivacyManager {
- return {
- deletePlaylistPrivacy: (key: number) => {
- return this.deleteConstant({ npmName: this.npmName, type: 'playlistPrivacy', obj: VIDEO_PLAYLIST_PRIVACIES, key })
- }
- }
- }
-
- private buildVideoLicenceManager (): PluginVideoLicenceManager {
- return {
- addLicence: (key: number, label: string) => {
- return this.addConstant({ npmName: this.npmName, type: 'licence', obj: VIDEO_LICENCES, key, label })
- },
-
- deleteLicence: (key: number) => {
- return this.deleteConstant({ npmName: this.npmName, type: 'licence', obj: VIDEO_LICENCES, key })
- }
- }
- }
-
- private addConstant<T extends string | number> (parameters: {
- npmName: string
- type: AlterableVideoConstant
- obj: VideoConstant
- key: T
- label: string
- }) {
- const { npmName, type, obj, key, label } = parameters
-
- if (obj[key]) {
- logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
- return false
- }
-
- if (!this.updatedVideoConstants[type][npmName]) {
- this.updatedVideoConstants[type][npmName] = {
- added: [],
- deleted: []
- }
- }
-
- this.updatedVideoConstants[type][npmName].added.push({ key, label })
- obj[key] = label
-
- return true
- }
-
- private deleteConstant<T extends string | number> (parameters: {
- npmName: string
- type: AlterableVideoConstant
- obj: VideoConstant
- key: T
- }) {
- const { npmName, type, obj, key } = parameters
-
- if (!obj[key]) {
- logger.warn('Cannot delete %s by plugin %s: key %s does not exist.', type, npmName, key)
- return false
- }
-
- if (!this.updatedVideoConstants[type][npmName]) {
- this.updatedVideoConstants[type][npmName] = {
- added: [],
- deleted: []
- }
- }
-
- const updatedConstants = this.updatedVideoConstants[type][npmName]
-
- const alreadyAdded = updatedConstants.added.find(a => a.key === key)
- if (alreadyAdded) {
- updatedConstants.added.filter(a => a.key !== key)
- } else if (obj[key]) {
- updatedConstants.deleted.push({ key, label: obj[key] })
- }
-
- delete obj[key]
-
- return true
- }
-
private buildTranscodingManager () {
const self = this
--- /dev/null
+import { logger } from '@server/helpers/logger'
+import {
+ VIDEO_CATEGORIES,
+ VIDEO_LANGUAGES,
+ VIDEO_LICENCES,
+ VIDEO_PLAYLIST_PRIVACIES,
+ VIDEO_PRIVACIES
+} from '@server/initializers/constants'
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
+
+type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy'
+type VideoConstant = Record<number | string, string>
+
+type UpdatedVideoConstant = {
+ [name in AlterableVideoConstant]: {
+ [ npmName: string]: {
+ added: VideoConstant[]
+ deleted: VideoConstant[]
+ }
+ }
+}
+
+const constantsHash: { [key in AlterableVideoConstant]: VideoConstant } = {
+ language: VIDEO_LANGUAGES,
+ licence: VIDEO_LICENCES,
+ category: VIDEO_CATEGORIES,
+ privacy: VIDEO_PRIVACIES,
+ playlistPrivacy: VIDEO_PLAYLIST_PRIVACIES
+}
+
+export class VideoConstantManagerFactory {
+ private readonly updatedVideoConstants: UpdatedVideoConstant = {
+ playlistPrivacy: { },
+ privacy: { },
+ language: { },
+ licence: { },
+ category: { }
+ }
+
+ constructor (
+ private readonly npmName: string
+ ) {}
+
+ public resetVideoConstants (npmName: string) {
+ const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category', 'privacy', 'playlistPrivacy' ]
+ for (const type of types) {
+ this.resetConstants({ npmName, type })
+ }
+ }
+
+ private resetConstants (parameters: { npmName: string, type: AlterableVideoConstant }) {
+ const { npmName, type } = parameters
+ const updatedConstants = this.updatedVideoConstants[type][npmName]
+
+ if (!updatedConstants) return
+
+ for (const added of updatedConstants.added) {
+ delete constantsHash[type][added.key]
+ }
+
+ for (const deleted of updatedConstants.deleted) {
+ constantsHash[type][deleted.key] = deleted.label
+ }
+
+ delete this.updatedVideoConstants[type][npmName]
+ }
+
+ public createVideoConstantManager<K extends number | string>(type: AlterableVideoConstant): ConstantManager<K> {
+ const { npmName } = this
+ return {
+ addConstant: (key: K, label: string) => this.addConstant({ npmName, type, key, label }),
+ deleteConstant: (key: K) => this.deleteConstant({ npmName, type, key }),
+ getConstantValue: (key: K) => constantsHash[type][key],
+ getConstants: () => constantsHash[type] as Record<K, string>,
+ resetConstants: () => this.resetConstants({ npmName, type })
+ }
+ }
+
+ private addConstant<T extends string | number> (parameters: {
+ npmName: string
+ type: AlterableVideoConstant
+ key: T
+ label: string
+ }) {
+ const { npmName, type, key, label } = parameters
+ const obj = constantsHash[type]
+
+ if (obj[key]) {
+ logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
+ return false
+ }
+
+ if (!this.updatedVideoConstants[type][npmName]) {
+ this.updatedVideoConstants[type][npmName] = {
+ added: [],
+ deleted: []
+ }
+ }
+
+ this.updatedVideoConstants[type][npmName].added.push({ key: key, label } as VideoConstant)
+ obj[key] = label
+
+ return true
+ }
+
+ private deleteConstant<T extends string | number> (parameters: {
+ npmName: string
+ type: AlterableVideoConstant
+ key: T
+ }) {
+ const { npmName, type, key } = parameters
+ const obj = constantsHash[type]
+
+ if (!obj[key]) {
+ logger.warn('Cannot delete %s by plugin %s: key %s does not exist.', type, npmName, key)
+ return false
+ }
+
+ if (!this.updatedVideoConstants[type][npmName]) {
+ this.updatedVideoConstants[type][npmName] = {
+ added: [],
+ deleted: []
+ }
+ }
+
+ const updatedConstants = this.updatedVideoConstants[type][npmName]
+
+ const alreadyAdded = updatedConstants.added.find(a => a.key === key)
+ if (alreadyAdded) {
+ updatedConstants.added.filter(a => a.key !== key)
+ } else if (obj[key]) {
+ updatedConstants.deleted.push({ key, label: obj[key] } as VideoConstant)
+ }
+
+ delete obj[key]
+
+ return true
+ }
+}
+import { chunk } from 'lodash'
+import { compareSemVer } from '@shared/core-utils'
import { logger } from '../../helpers/logger'
-import { AbstractScheduler } from './abstract-scheduler'
-import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants'
import { CONFIG } from '../../initializers/config'
+import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants'
import { PluginModel } from '../../models/server/plugin'
-import { chunk } from 'lodash'
-import { getLatestPluginsVersion } from '../plugins/plugin-index'
-import { compareSemVer } from '../../../shared/core-utils/miscs/miscs'
import { Notifier } from '../notifier'
+import { getLatestPluginsVersion } from '../plugins/plugin-index'
+import { AbstractScheduler } from './abstract-scheduler'
export class PluginsCheckScheduler extends AbstractScheduler {
logger.info('Duplicating %s streaming playlist in videos redundancy with "%s" strategy.', video.url, strategy)
const destDirectory = join(HLS_REDUNDANCY_DIRECTORY, video.uuid)
- await downloadPlaylistSegments(playlist.playlistUrl, destDirectory, VIDEO_IMPORT_TIMEOUT)
+ const masterPlaylistUrl = playlist.getMasterPlaylistUrl(video)
+ await downloadPlaylistSegments(masterPlaylistUrl, destDirectory, VIDEO_IMPORT_TIMEOUT)
const createdModel: MVideoRedundancyStreamingPlaylistVideo = await VideoRedundancyModel.create({
expiresOn,
await sendCreateCacheFile(serverActor, video, createdModel)
- logger.info('Duplicated playlist %s -> %s.', playlist.playlistUrl, createdModel.url)
+ logger.info('Duplicated playlist %s -> %s.', masterPlaylistUrl, createdModel.url)
}
private async extendsExpirationOf (redundancy: MVideoRedundancyVideo, expiresAfterMs: number) {
private buildEntryLogId (object: MVideoRedundancyFileVideo | MVideoRedundancyStreamingPlaylistVideo) {
if (isMVideoRedundancyFileVideo(object)) return `${object.VideoFile.Video.url}-${object.VideoFile.resolution}`
- return `${object.VideoStreamingPlaylist.playlistUrl}`
+ return `${object.VideoStreamingPlaylist.getMasterPlaylistUrl(object.VideoStreamingPlaylist.Video)}`
}
private getTotalFileSizes (files: MVideoFile[], playlists: MStreamingPlaylistFiles[]) {
import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../../helpers/ffprobe-utils'
import { logger } from '../../helpers/logger'
import { CONFIG } from '../../initializers/config'
-import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../../initializers/constants'
+import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION } from '../../initializers/constants'
import { VideoFileModel } from '../../models/video/video-file'
import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls'
-import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from '../video-paths'
+import {
+ generateHLSMasterPlaylistFilename,
+ generateHlsSha256SegmentsFilename,
+ generateHLSVideoFilename,
+ generateWebTorrentVideoFilename,
+ getHlsResolutionPlaylistFilename,
+ getVideoFilePath
+} from '../video-paths'
import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
/**
// Important to do this before getVideoFilename() to take in account the new filename
inputVideoFile.extname = newExtname
- inputVideoFile.filename = generateVideoFilename(video, false, resolution, newExtname)
+ inputVideoFile.filename = generateWebTorrentVideoFilename(resolution, newExtname)
const videoOutputPath = getVideoFilePath(video, inputVideoFile)
const newVideoFile = new VideoFileModel({
resolution,
extname,
- filename: generateVideoFilename(video, false, resolution, extname),
+ filename: generateWebTorrentVideoFilename(resolution, extname),
size: 0,
videoId: video.id
})
// Important to do this before getVideoFilename() to take in account the new file extension
inputVideoFile.extname = newExtname
- inputVideoFile.filename = generateVideoFilename(video, false, inputVideoFile.resolution, newExtname)
+ inputVideoFile.filename = generateWebTorrentVideoFilename(inputVideoFile.resolution, newExtname)
const videoOutputPath = getVideoFilePath(video, inputVideoFile)
// ffmpeg generated a new video file, so update the video duration
const videoTranscodedBasePath = join(transcodeDirectory, type)
await ensureDir(videoTranscodedBasePath)
- const videoFilename = generateVideoStreamingPlaylistName(video.uuid, resolution)
- const playlistFilename = VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution)
- const playlistFileTranscodePath = join(videoTranscodedBasePath, playlistFilename)
+ const videoFilename = generateHLSVideoFilename(resolution)
+ const resolutionPlaylistFilename = getHlsResolutionPlaylistFilename(videoFilename)
+ const resolutionPlaylistFileTranscodePath = join(videoTranscodedBasePath, resolutionPlaylistFilename)
const transcodeOptions = {
type,
inputPath,
- outputPath: playlistFileTranscodePath,
+ outputPath: resolutionPlaylistFileTranscodePath,
availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(),
profile: CONFIG.TRANSCODING.PROFILE,
await transcode(transcodeOptions)
- const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
-
// Create or update the playlist
- const [ videoStreamingPlaylist ] = await VideoStreamingPlaylistModel.upsert({
- videoId: video.id,
- playlistUrl,
- segmentsSha256Url: WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid, video.isLive),
- p2pMediaLoaderInfohashes: [],
- p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
+ const playlist = await VideoStreamingPlaylistModel.loadOrGenerate(video)
+
+ if (!playlist.playlistFilename) {
+ playlist.playlistFilename = generateHLSMasterPlaylistFilename(video.isLive)
+ }
+
+ if (!playlist.segmentsSha256Filename) {
+ playlist.segmentsSha256Filename = generateHlsSha256SegmentsFilename(video.isLive)
+ }
+
+ playlist.p2pMediaLoaderInfohashes = []
+ playlist.p2pMediaLoaderPeerVersion = P2P_MEDIA_LOADER_PEER_VERSION
- type: VideoStreamingPlaylistType.HLS
- }, { returning: true }) as [ MStreamingPlaylistFilesVideo, boolean ]
- videoStreamingPlaylist.Video = video
+ playlist.type = VideoStreamingPlaylistType.HLS
+
+ await playlist.save()
// Build the new playlist file
const extname = extnameUtil(videoFilename)
resolution,
extname,
size: 0,
- filename: generateVideoFilename(video, true, resolution, extname),
+ filename: videoFilename,
fps: -1,
- videoStreamingPlaylistId: videoStreamingPlaylist.id
+ videoStreamingPlaylistId: playlist.id
})
- const videoFilePath = getVideoFilePath(videoStreamingPlaylist, newVideoFile)
+ const videoFilePath = getVideoFilePath(playlist, newVideoFile)
// Move files from tmp transcoded directory to the appropriate place
const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
await ensureDir(baseHlsDirectory)
// Move playlist file
- const playlistPath = join(baseHlsDirectory, playlistFilename)
- await move(playlistFileTranscodePath, playlistPath, { overwrite: true })
+ const resolutionPlaylistPath = join(baseHlsDirectory, resolutionPlaylistFilename)
+ await move(resolutionPlaylistFileTranscodePath, resolutionPlaylistPath, { overwrite: true })
// Move video file
await move(join(videoTranscodedBasePath, videoFilename), videoFilePath, { overwrite: true })
newVideoFile.fps = await getVideoFileFPS(videoFilePath)
newVideoFile.metadata = await getMetadataFromFile(videoFilePath)
- await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile)
+ await createTorrentAndSetInfoHash(playlist, newVideoFile)
await VideoFileModel.customUpsert(newVideoFile, 'streaming-playlist', undefined)
- videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles')
- videoStreamingPlaylist.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(
- playlistUrl, videoStreamingPlaylist.VideoFiles
- )
- await videoStreamingPlaylist.save()
+ const playlistWithFiles = playlist as MStreamingPlaylistFilesVideo
+ playlistWithFiles.VideoFiles = await playlist.$get('VideoFiles')
+ playlist.assignP2PMediaLoaderInfoHashes(video, playlistWithFiles.VideoFiles)
+
+ await playlist.save()
- video.setHLSPlaylist(videoStreamingPlaylist)
+ video.setHLSPlaylist(playlist)
- await updateMasterHLSPlaylist(video)
- await updateSha256VODSegments(video)
+ await updateMasterHLSPlaylist(video, playlistWithFiles)
+ await updateSha256VODSegments(video, playlistWithFiles)
- return playlistPath
+ return resolutionPlaylistPath
}
import { CONFIG } from '@server/initializers/config'
import { HLS_REDUNDANCY_DIRECTORY, HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_PATHS, WEBSERVER } from '@server/initializers/constants'
import { isStreamingPlaylist, MStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models'
+import { buildUUID } from '@server/helpers/uuid'
+import { removeFragmentedMP4Ext } from '@shared/core-utils'
// ################## Video file name ##################
-function generateVideoFilename (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, isHls: boolean, resolution: number, extname: string) {
- const video = extractVideo(videoOrPlaylist)
-
- // FIXME: use a generated uuid instead, that will break compatibility with PeerTube < 3.1
- // const uuid = uuidv4()
- const uuid = video.uuid
-
- if (isHls) {
- return generateVideoStreamingPlaylistName(uuid, resolution)
- }
-
- return generateWebTorrentVideoName(uuid, resolution, extname)
+function generateWebTorrentVideoFilename (resolution: number, extname: string) {
+ return buildUUID() + '-' + resolution + extname
}
-function generateVideoStreamingPlaylistName (uuid: string, resolution: number) {
- return `${uuid}-${resolution}-fragmented.mp4`
-}
-
-function generateWebTorrentVideoName (uuid: string, resolution: number, extname: string) {
- return uuid + '-' + resolution + extname
+function generateHLSVideoFilename (resolution: number) {
+ return `${buildUUID()}-${resolution}-fragmented.mp4`
}
function getVideoFilePath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile, isRedundancy = false) {
return join(baseDir, video.uuid)
}
+function getHlsResolutionPlaylistFilename (videoFilename: string) {
+ // Video file name already contain resolution
+ return removeFragmentedMP4Ext(videoFilename) + '.m3u8'
+}
+
+function generateHLSMasterPlaylistFilename (isLive = false) {
+ if (isLive) return 'master.m3u8'
+
+ return buildUUID() + '-master.m3u8'
+}
+
+function generateHlsSha256SegmentsFilename (isLive = false) {
+ if (isLive) return 'segments-sha256.json'
+
+ return buildUUID() + '-segments-sha256.json'
+}
+
// ################## Torrents ##################
function generateTorrentFileName (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, resolution: number) {
- const video = extractVideo(videoOrPlaylist)
const extension = '.torrent'
-
- // FIXME: use a generated uuid instead, that will break compatibility with PeerTube < 3.1
- // const uuid = uuidv4()
- const uuid = video.uuid
+ const uuid = buildUUID()
if (isStreamingPlaylist(videoOrPlaylist)) {
return `${uuid}-${resolution}-${videoOrPlaylist.getStringType()}${extension}`
// ---------------------------------------------------------------------------
export {
- generateVideoStreamingPlaylistName,
- generateWebTorrentVideoName,
- generateVideoFilename,
+ generateHLSVideoFilename,
+ generateWebTorrentVideoFilename,
+
getVideoFilePath,
generateTorrentFileName,
getTorrentFilePath,
getHLSDirectory,
+ generateHLSMasterPlaylistFilename,
+ generateHlsSha256SegmentsFilename,
+ getHlsResolutionPlaylistFilename,
getLocalVideoFileMetadataUrl,
import { TagModel } from '@server/models/video/tag'
import { VideoModel } from '@server/models/video/video'
import { FilteredModelAttributes } from '@server/types'
-import { MThumbnail, MUserId, MVideo, MVideoFile, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models'
+import { MThumbnail, MUserId, MVideoFile, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models'
import { ThumbnailType, VideoCreate, VideoPrivacy, VideoTranscodingPayload } from '@shared/models'
import { federateVideoIfNeeded } from './activitypub/videos'
import { JobQueue } from './job-queue/job-queue'
}
}
-async function addOptimizeOrMergeAudioJob (video: MVideo, videoFile: MVideoFile, user: MUserId) {
+async function addOptimizeOrMergeAudioJob (video: MVideoUUID, videoFile: MVideoFile, user: MUserId) {
let dataInput: VideoTranscodingPayload
if (videoFile.isAudio()) {
import { getAPId } from '@server/helpers/activitypub'
import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor'
import { ActivityDelete, ActivityPubSignature } from '../../shared'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto'
import { ACCEPT_HEADERS, ACTIVITY_PUB, HTTP_SIGNATURE } from '../initializers/constants'
import * as express from 'express'
import { Socket } from 'socket.io'
import { getAccessToken } from '@server/lib/auth/oauth-model'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
import { handleOAuthAuthenticate } from '../lib/auth/oauth'
+++ /dev/null
-import { Redis } from '../lib/redis'
-import * as apicache from 'apicache'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
-
-// Ensure Redis is initialized
-Redis.Instance.init()
-
-const defaultOptions = {
- redisClient: Redis.Instance.getClient(),
- appendKey: () => Redis.Instance.getPrefix(),
- statusCodes: {
- exclude: [
- HttpStatusCode.FORBIDDEN_403,
- HttpStatusCode.NOT_FOUND_404
- ]
- }
-}
-
-const cacheRoute = (extraOptions = {}) => apicache.options({
- ...defaultOptions,
- ...extraOptions
-}).middleware
-
-// ---------------------------------------------------------------------------
-
-export {
- cacheRoute
-}
--- /dev/null
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
+import { Redis } from '../../lib/redis'
+import { ApiCache, APICacheOptions } from './shared'
+
+// Ensure Redis is initialized
+Redis.Instance.init()
+
+const defaultOptions: APICacheOptions = {
+ excludeStatus: [
+ HttpStatusCode.FORBIDDEN_403,
+ HttpStatusCode.NOT_FOUND_404
+ ]
+}
+
+function cacheRoute (duration: string) {
+ const instance = new ApiCache(defaultOptions)
+
+ return instance.buildMiddleware(duration)
+}
+
+function cacheRouteFactory (options: APICacheOptions) {
+ const instance = new ApiCache({ ...defaultOptions, ...options })
+
+ return instance.buildMiddleware.bind(instance)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ cacheRoute,
+ cacheRouteFactory
+}
--- /dev/null
+export * from './cache'
--- /dev/null
+// Thanks: https://github.com/kwhitley/apicache
+// We duplicated the library because it is unmaintened and prevent us to upgrade to recent NodeJS versions
+
+import * as express from 'express'
+import { OutgoingHttpHeaders } from 'http'
+import { isTestInstance, parseDurationToMs } from '@server/helpers/core-utils'
+import { logger } from '@server/helpers/logger'
+import { Redis } from '@server/lib/redis'
+import { HttpStatusCode } from '@shared/models'
+
+export interface APICacheOptions {
+ headerBlacklist?: string[]
+ excludeStatus?: HttpStatusCode[]
+}
+
+interface CacheObject {
+ status: number
+ headers: OutgoingHttpHeaders
+ data: any
+ encoding: BufferEncoding
+ timestamp: number
+}
+
+export class ApiCache {
+
+ private readonly options: APICacheOptions
+ private readonly timers: { [ id: string ]: NodeJS.Timeout } = {}
+
+ private index: { all: string[] } = { all: [] }
+
+ constructor (options: APICacheOptions) {
+ this.options = {
+ headerBlacklist: [],
+ excludeStatus: [],
+
+ ...options
+ }
+ }
+
+ buildMiddleware (strDuration: string) {
+ const duration = parseDurationToMs(strDuration)
+
+ return (req: express.Request, res: express.Response, next: express.NextFunction) => {
+ const key = Redis.Instance.getPrefix() + 'api-cache-' + req.originalUrl
+ const redis = Redis.Instance.getClient()
+
+ if (!redis.connected) return this.makeResponseCacheable(res, next, key, duration)
+
+ try {
+ redis.hgetall(key, (err, obj) => {
+ if (!err && obj && obj.response) {
+ return this.sendCachedResponse(req, res, JSON.parse(obj.response), duration)
+ }
+
+ return this.makeResponseCacheable(res, next, key, duration)
+ })
+ } catch (err) {
+ return this.makeResponseCacheable(res, next, key, duration)
+ }
+ }
+ }
+
+ private shouldCacheResponse (response: express.Response) {
+ if (!response) return false
+ if (this.options.excludeStatus.includes(response.statusCode)) return false
+
+ return true
+ }
+
+ private addIndexEntries (key: string) {
+ this.index.all.unshift(key)
+ }
+
+ private filterBlacklistedHeaders (headers: OutgoingHttpHeaders) {
+ return Object.keys(headers)
+ .filter(key => !this.options.headerBlacklist.includes(key))
+ .reduce((acc, header) => {
+ acc[header] = headers[header]
+
+ return acc
+ }, {})
+ }
+
+ private createCacheObject (status: number, headers: OutgoingHttpHeaders, data: any, encoding: BufferEncoding) {
+ return {
+ status,
+ headers: this.filterBlacklistedHeaders(headers),
+ data,
+ encoding,
+
+ // Seconds since epoch, used to properly decrement max-age headers in cached responses.
+ timestamp: new Date().getTime() / 1000
+ } as CacheObject
+ }
+
+ private cacheResponse (key: string, value: object, duration: number) {
+ const redis = Redis.Instance.getClient()
+
+ if (redis.connected) {
+ try {
+ redis.hset(key, 'response', JSON.stringify(value))
+ redis.hset(key, 'duration', duration + '')
+ redis.expire(key, duration / 1000)
+ } catch (err) {
+ logger.error('Cannot set cache in redis.', { err })
+ }
+ }
+
+ // add automatic cache clearing from duration, includes max limit on setTimeout
+ this.timers[key] = setTimeout(() => this.clear(key), Math.min(duration, 2147483647))
+ }
+
+ private accumulateContent (res: express.Response, content: any) {
+ if (!content) return
+
+ if (typeof content === 'string') {
+ res.locals.apicache.content = (res.locals.apicache.content || '') + content
+ return
+ }
+
+ if (Buffer.isBuffer(content)) {
+ let oldContent = res.locals.apicache.content
+
+ if (typeof oldContent === 'string') {
+ oldContent = Buffer.from(oldContent)
+ }
+
+ if (!oldContent) {
+ oldContent = Buffer.alloc(0)
+ }
+
+ res.locals.apicache.content = Buffer.concat(
+ [ oldContent, content ],
+ oldContent.length + content.length
+ )
+
+ return
+ }
+
+ res.locals.apicache.content = content
+ }
+
+ private makeResponseCacheable (res: express.Response, next: express.NextFunction, key: string, duration: number) {
+ const self = this
+
+ res.locals.apicache = {
+ write: res.write,
+ writeHead: res.writeHead,
+ end: res.end,
+ cacheable: true,
+ content: undefined,
+ headers: {}
+ }
+
+ // Patch express
+ res.writeHead = function () {
+ if (self.shouldCacheResponse(res)) {
+ res.setHeader('cache-control', 'max-age=' + (duration / 1000).toFixed(0))
+ } else {
+ res.setHeader('cache-control', 'no-cache, no-store, must-revalidate')
+ }
+
+ res.locals.apicache.headers = Object.assign({}, res.getHeaders())
+ return res.locals.apicache.writeHead.apply(this, arguments as any)
+ }
+
+ res.write = function (chunk: any) {
+ self.accumulateContent(res, chunk)
+ return res.locals.apicache.write.apply(this, arguments as any)
+ }
+
+ res.end = function (content: any, encoding: BufferEncoding) {
+ if (self.shouldCacheResponse(res)) {
+ self.accumulateContent(res, content)
+
+ if (res.locals.apicache.cacheable && res.locals.apicache.content) {
+ self.addIndexEntries(key)
+
+ const headers = res.locals.apicache.headers || res.getHeaders()
+ const cacheObject = self.createCacheObject(
+ res.statusCode,
+ headers,
+ res.locals.apicache.content,
+ encoding
+ )
+ self.cacheResponse(key, cacheObject, duration)
+ }
+ }
+
+ res.locals.apicache.end.apply(this, arguments as any)
+ } as any
+
+ next()
+ }
+
+ private sendCachedResponse (request: express.Request, response: express.Response, cacheObject: CacheObject, duration: number) {
+ const headers = response.getHeaders()
+
+ if (isTestInstance()) {
+ Object.assign(headers, {
+ 'x-api-cache-cached': 'true'
+ })
+ }
+
+ Object.assign(headers, this.filterBlacklistedHeaders(cacheObject.headers || {}), {
+ // Set properly decremented max-age header
+ // This ensures that max-age is in sync with the cache expiration
+ 'cache-control':
+ 'max-age=' +
+ Math.max(
+ 0,
+ (duration / 1000 - (new Date().getTime() / 1000 - cacheObject.timestamp))
+ ).toFixed(0)
+ })
+
+ // unstringify buffers
+ let data = cacheObject.data
+ if (data && data.type === 'Buffer') {
+ data = typeof data.data === 'number'
+ ? Buffer.alloc(data.data)
+ : Buffer.from(data.data)
+ }
+
+ // Test Etag against If-None-Match for 304
+ const cachedEtag = cacheObject.headers.etag
+ const requestEtag = request.headers['if-none-match']
+
+ if (requestEtag && cachedEtag === requestEtag) {
+ response.writeHead(304, headers)
+ return response.end()
+ }
+
+ response.writeHead(cacheObject.status || 200, headers)
+
+ return response.end(data, cacheObject.encoding)
+ }
+
+ private clear (target: string) {
+ const redis = Redis.Instance.getClient()
+
+ if (target) {
+ clearTimeout(this.timers[target])
+ delete this.timers[target]
+
+ try {
+ redis.del(target)
+ } catch (err) {
+ logger.error('Cannot delete %s in redis cache.', target, { err })
+ }
+
+ this.index.all = this.index.all.filter(key => key !== target)
+ } else {
+ for (const key of this.index.all) {
+ clearTimeout(this.timers[key])
+ delete this.timers[key]
+
+ try {
+ redis.del(key)
+ } catch (err) {
+ logger.error('Cannot delete %s in redis cache.', key, { err })
+ }
+ }
+
+ this.index.all = []
+ }
+
+ return this.index
+ }
+}
--- /dev/null
+export * from './api-cache'
import * as express from 'express'
import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
function apiFailMiddleware (req: express.Request, res: express.Response, next: express.NextFunction) {
res.fail = options => {
export * from './validators'
+export * from './cache'
export * from './activitypub'
export * from './async'
export * from './auth'
import * as express from 'express'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { getHostWithPort } from '../helpers/express-utils'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) {
if (!req.body.hosts) return next()
import * as express from 'express'
import { UserRight } from '../../shared'
+import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
function ensureUserHasRight (userRight: UserRight) {
return function (req: express.Request, res: express.Response, next: express.NextFunction) {
import { logger } from '@server/helpers/logger'
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
import { AbuseCreate, UserRight } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared'
const abuseReportValidator = [
import * as express from 'express'
+import { getServerActor } from '@server/models/application/application'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity'
import { logger } from '../../../helpers/logger'
-import { getServerActor } from '@server/models/application/application'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
async function activityPubValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
logger.debug('Checking activity pub parameters')
import * as express from 'express'
import { body, param } from 'express-validator'
import { getServerActor } from '@server/models/application/application'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isHostValid } from '../../helpers/custom-validators/servers'
import { logger } from '../../helpers/logger'
import { WEBSERVER } from '../../initializers/constants'
import * as express from 'express'
import { body } from 'express-validator'
import { isBulkRemoveCommentsOfScopeValid } from '@server/helpers/custom-validators/bulk'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { UserRight } from '@shared/models'
+import { HttpStatusCode, UserRight } from '@shared/models'
import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model'
import { logger } from '../../helpers/logger'
import { areValidationErrors, doesAccountNameWithHostExist } from './shared'
import * as express from 'express'
import { param, query } from 'express-validator'
-
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isValidRSSFeed } from '../../helpers/custom-validators/feeds'
import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
import { logger } from '../../helpers/logger'
import * as express from 'express'
import { body, param, query } from 'express-validator'
-import { isFollowStateValid } from '@server/helpers/custom-validators/follows'
+import { isEachUniqueHandleValid, isFollowStateValid, isRemoteHandleValid } from '@server/helpers/custom-validators/follows'
import { loadActorUrlOrGetFromWebfinger } from '@server/lib/activitypub/actors'
+import { getRemoteNameAndHost } from '@server/lib/activitypub/follow'
import { getServerActor } from '@server/models/application/application'
import { MActorFollowActorsDefault } from '@server/types/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isTestInstance } from '../../helpers/core-utils'
import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers'
import { logger } from '../../helpers/logger'
-import { SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
+import { WEBSERVER } from '../../initializers/constants'
import { ActorModel } from '../../models/actor/actor'
import { ActorFollowModel } from '../../models/actor/actor-follow'
import { areValidationErrors } from './shared'
+import { ServerFollowCreate } from '@shared/models'
const listFollowsValidator = [
query('state')
]
const followValidator = [
- body('hosts').custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
+ body('hosts')
+ .toArray()
+ .custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
+
+ body('handles')
+ .toArray()
+ .custom(isEachUniqueHandleValid).withMessage('Should have an array of handles'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
- // Force https if the administrator wants to make friends
+ // Force https if the administrator wants to follow remote actors
if (isTestInstance() === false && WEBSERVER.SCHEME === 'http') {
return res
.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
.json({
error: 'Cannot follow on a non HTTPS web server.'
})
- .end()
}
logger.debug('Checking follow parameters', { parameters: req.body })
if (areValidationErrors(req, res)) return
+ const body: ServerFollowCreate = req.body
+ if (body.hosts.length === 0 && body.handles.length === 0) {
+
+ return res
+ .status(HttpStatusCode.BAD_REQUEST_400)
+ .json({
+ error: 'You must provide at least one handle or one host.'
+ })
+ }
+
return next()
}
]
const removeFollowingValidator = [
- param('host').custom(isHostValid).withMessage('Should have a valid host'),
+ param('hostOrHandle')
+ .custom(value => isHostValid(value) || isRemoteHandleValid(value))
+ .withMessage('Should have a valid host/handle'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking unfollowing parameters', { parameters: req.params })
if (areValidationErrors(req, res)) return
const serverActor = await getServerActor()
- const follow = await ActorFollowModel.loadByActorAndTargetNameAndHostForAPI(serverActor.id, SERVER_ACTOR_NAME, req.params.host)
+
+ const { name, host } = getRemoteNameAndHost(req.params.hostOrHandle)
+ const follow = await ActorFollowModel.loadByActorAndTargetNameAndHostForAPI(serverActor.id, name, host)
if (!follow) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
- message: `Following ${req.params.host} not found.`
+ message: `Follow ${req.params.hostOrHandle} not found.`
})
}
import { loadVideo } from '@server/lib/model-loaders'
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isTestInstance } from '../../helpers/core-utils'
import { isIdOrUUIDValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
import { logger } from '../../helpers/logger'
import * as express from 'express'
import { body, param, query, ValidationChain } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { PluginType } from '../../../shared/models/plugins/plugin.type'
import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model'
import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
import * as express from 'express'
import { body, param, query } from 'express-validator'
import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import {
exists,
isBooleanValid,
import * as express from 'express'
import { query } from 'express-validator'
import { isSearchTargetValid } from '@server/helpers/custom-validators/search'
-import { isDateValid } from '../../helpers/custom-validators/misc'
+import { isHostValid } from '@server/helpers/custom-validators/servers'
+import { areUUIDsValid, isDateValid, isNotEmptyStringArray, toCompleteUUIDs } from '../../helpers/custom-validators/misc'
import { logger } from '../../helpers/logger'
import { areValidationErrors } from './shared'
const videosSearchValidator = [
query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
+ query('host')
+ .optional()
+ .custom(isHostValid).withMessage('Should have a valid host'),
+
query('startDate')
.optional()
.custom(isDateValid).withMessage('Should have a start date that conforms to ISO 8601'),
.optional()
.custom(isDateValid).withMessage('Should have a published end date that conforms to ISO 8601'),
- query('durationMin').optional().isInt().withMessage('Should have a valid min duration'),
- query('durationMax').optional().isInt().withMessage('Should have a valid max duration'),
+ query('durationMin')
+ .optional()
+ .isInt().withMessage('Should have a valid min duration'),
+ query('durationMax')
+ .optional()
+ .isInt().withMessage('Should have a valid max duration'),
+
+ query('uuids')
+ .optional()
+ .toArray()
+ .customSanitizer(toCompleteUUIDs)
+ .custom(areUUIDsValid).withMessage('Should have valid uuids'),
query('searchTarget').optional().custom(isSearchTargetValid).withMessage('Should have a valid search target'),
]
const videoChannelsListSearchValidator = [
- query('search').not().isEmpty().withMessage('Should have a valid search'),
- query('searchTarget').optional().custom(isSearchTargetValid).withMessage('Should have a valid search target'),
+ query('search')
+ .optional()
+ .not().isEmpty().withMessage('Should have a valid search'),
+
+ query('host')
+ .optional()
+ .custom(isHostValid).withMessage('Should have a valid host'),
+
+ query('searchTarget')
+ .optional()
+ .custom(isSearchTargetValid).withMessage('Should have a valid search target'),
+
+ query('handles')
+ .optional()
+ .toArray()
+ .custom(isNotEmptyStringArray).withMessage('Should have valid handles'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking video channels search query', { parameters: req.query })
]
const videoPlaylistsListSearchValidator = [
- query('search').not().isEmpty().withMessage('Should have a valid search'),
- query('searchTarget').optional().custom(isSearchTargetValid).withMessage('Should have a valid search target'),
+ query('search')
+ .optional()
+ .not().isEmpty().withMessage('Should have a valid search'),
+
+ query('host')
+ .optional()
+ .custom(isHostValid).withMessage('Should have a valid host'),
+
+ query('searchTarget')
+ .optional()
+ .custom(isSearchTargetValid).withMessage('Should have a valid search target'),
+
+ query('uuids')
+ .optional()
+ .toArray()
+ .customSanitizer(toCompleteUUIDs)
+ .custom(areUUIDsValid).withMessage('Should have valid uuids'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking video playlists search query', { parameters: req.query })
import * as express from 'express'
import { body } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isHostValid, isValidContactBody } from '../../helpers/custom-validators/servers'
import { isUserDisplayNameValid } from '../../helpers/custom-validators/users'
import { logger } from '../../helpers/logger'
import { Response } from 'express'
import { AbuseModel } from '@server/models/abuse/abuse'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesAbuseExist (abuseId: number | string, res: Response) {
const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10))
import { AccountModel } from '@server/models/account/account'
import { UserModel } from '@server/models/user/user'
import { MAccountDefault } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) {
const promise = AccountModel.load(parseInt(id + '', 10))
import { Response } from 'express'
import { VideoBlacklistModel } from '@server/models/video/video-blacklist'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesVideoBlacklistExist (videoId: number, res: Response) {
const videoBlacklist = await VideoBlacklistModel.loadByVideoId(videoId)
import { Response } from 'express'
import { VideoCaptionModel } from '@server/models/video/video-caption'
import { MVideoId } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesVideoCaptionExist (video: MVideoId, language: string, res: Response) {
const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, language)
import * as express from 'express'
import { VideoChannelModel } from '@server/models/video/video-channel'
import { MChannelBannerAccountDefault } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesLocalVideoChannelNameExist (name: string, res: express.Response) {
const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
import * as express from 'express'
import { VideoCommentModel } from '@server/models/video/video-comment'
import { MVideoId } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) {
const id = parseInt(idArg + '', 10)
import * as express from 'express'
import { VideoImportModel } from '@server/models/video/video-import'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesVideoImportExist (id: number, res: express.Response) {
const videoImport = await VideoImportModel.loadAndPopulateVideo(id)
import * as express from 'express'
import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
async function doesChangeVideoOwnershipExist (idArg: number | string, res: express.Response) {
const id = parseInt(idArg + '', 10)
import * as express from 'express'
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { MVideoPlaylist } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
export type VideoPlaylistFetchType = 'summary' | 'all'
async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: VideoPlaylistFetchType = 'summary') {
MVideoImmutable,
MVideoThumbnail
} from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
-import { UserRight } from '@shared/models'
+import { HttpStatusCode, UserRight } from '@shared/models'
async function doesVideoExist (id: number | string, res: Response, fetchType: VideoLoadType = 'all') {
const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
import * as express from 'express'
import { param } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isSafePath } from '../../helpers/custom-validators/misc'
import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins'
import { logger } from '../../helpers/logger'
import * as express from 'express'
import { body, param, query } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
import { toArray } from '../../helpers/custom-validators/misc'
import { logger } from '../../helpers/logger'
import { omit } from 'lodash'
import { Hooks } from '@server/lib/plugins/hooks'
import { MUserDefault } from '@server/types/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { UserRole } from '../../../shared/models/users'
import { UserRegister } from '../../../shared/models/users/user-register.model'
import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
import * as express from 'express'
import { body, query } from 'express-validator'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isBooleanValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../../helpers/custom-validators/video-blacklist'
import { logger } from '../../../helpers/logger'
import { VIDEO_CHANNELS } from '@server/initializers/constants'
import { MChannelAccountDefault, MUser } from '@server/types/models'
import { UserRight } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor'
import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
import {
import { body, param, query } from 'express-validator'
import { MUserAccountUrl } from '@server/types/models'
import { UserRight } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { exists, isBooleanValid, isIdValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments'
import { logger } from '../../../helpers/logger'
import { body } from 'express-validator'
import { isPreImportVideoAccepted } from '@server/lib/moderation'
import { Hooks } from '@server/lib/plugins/hooks'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
import { VideoImportCreate } from '@shared/models/videos/import/video-import-create.model'
import { isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc'
import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../../helpers/custom-validators/video-imports'
import { Hooks } from '@server/lib/plugins/hooks'
import { VideoModel } from '@server/models/video/video'
import { VideoLiveModel } from '@server/models/video/video-live'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { ServerErrorCode, UserRight, VideoState } from '@shared/models'
+import { HttpStatusCode, ServerErrorCode, UserRight, VideoState } from '@shared/models'
import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
import { isVideoNameValid } from '../../../helpers/custom-validators/videos'
import { cleanUpReqFiles } from '../../../helpers/express-utils'
import { isAbleToUploadVideo } from '@server/lib/user'
import { AccountModel } from '@server/models/account/account'
import { MVideoWithAllFiles } from '@server/types/models'
-import { HttpStatusCode } from '@shared/core-utils'
-import { ServerErrorCode, UserRight, VideoChangeOwnershipAccept, VideoChangeOwnershipStatus, VideoState } from '@shared/models'
+import {
+ HttpStatusCode,
+ ServerErrorCode,
+ UserRight,
+ VideoChangeOwnershipAccept,
+ VideoChangeOwnershipStatus,
+ VideoState
+} from '@shared/models'
import {
areValidationErrors,
checkUserCanManageVideo,
import { ExpressPromiseHandler } from '@server/types/express'
import { MUserAccountId } from '@server/types/models'
import { UserRight, VideoPlaylistCreate, VideoPlaylistUpdate } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
import {
import * as express from 'express'
import { body, param, query } from 'express-validator'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoRateType } from '../../../../shared/models/videos'
import { isAccountNameValid } from '../../../helpers/custom-validators/accounts'
import { isIdValid } from '../../../helpers/custom-validators/misc'
import * as express from 'express'
import { param } from 'express-validator'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isIdValid } from '../../../helpers/custom-validators/misc'
import { logger } from '../../../helpers/logger'
import { VideoShareModel } from '../../../models/video/video-share'
import * as express from 'express'
import { body } from 'express-validator'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { toIntOrNull } from '../../../helpers/custom-validators/misc'
import { logger } from '../../../helpers/logger'
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared'
import { ExpressPromiseHandler } from '@server/types/express'
import { MUserAccountId, MVideoFullLight } from '@server/types/models'
import { ServerErrorCode, UserRight, VideoPrivacy } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import {
exists,
isBooleanValid,
import * as express from 'express'
import { query } from 'express-validator'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isWebfingerLocalResourceValid } from '../../helpers/custom-validators/webfinger'
import { getHostWithPort } from '../../helpers/express-utils'
import { logger } from '../../helpers/logger'
export type SummaryOptions = {
actorRequired?: boolean // Default: true
whereActor?: WhereOptions
+ whereServer?: WhereOptions
withAccountBlockerIds?: number[]
}
}))
@Scopes(() => ({
[ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => {
- const whereActor = options.whereActor || undefined
-
const serverInclude: IncludeOptions = {
attributes: [ 'host' ],
model: ServerModel.unscoped(),
- required: false
+ required: !!options.whereServer,
+ where: options.whereServer
}
const queryInclude: Includeable[] = [
attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
model: ActorModel.unscoped(),
required: options.actorRequired ?? true,
- where: whereActor,
+ where: options.whereActor,
include: [
serverInclude,
} from 'sequelize-typescript'
import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc'
import { getServerActor } from '@server/models/application/application'
-import { VideoModel } from '@server/models/video/video'
import {
MActorFollowActorsDefault,
MActorFollowActorsDefaultSubscription,
import { ACTOR_FOLLOW_SCORE, CONSTRAINTS_FIELDS, FOLLOW_STATES, SERVER_ACTOR_NAME } from '../../initializers/constants'
import { AccountModel } from '../account/account'
import { ServerModel } from '../server/server'
+import { doesExist } from '../shared/query'
import { createSafeIn, getFollowsSort, getSort, searchAttribute, throwIfNotValid } from '../utils'
import { VideoChannelModel } from '../video/video-channel'
import { ActorModel, unusedActorAttributesForAPI } from './actor'
static isFollowedBy (actorId: number, followerActorId: number) {
const query = 'SELECT 1 FROM "actorFollow" WHERE "actorId" = $followerActorId AND "targetActorId" = $actorId LIMIT 1'
- const options = {
- type: QueryTypes.SELECT as QueryTypes.SELECT,
- bind: { actorId, followerActorId },
- raw: true
- }
- return VideoModel.sequelize.query(query, options)
- .then(results => results.length === 1)
+ return doesExist(query, { actorId, followerActorId })
}
static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Promise<MActorFollowActorsDefault> {
const followWhere = state ? { state } : {}
const followingWhere: WhereOptions = {}
- const followingServerWhere: WhereOptions = {}
if (search) {
- Object.assign(followingServerWhere, {
- host: {
- [Op.iLike]: '%' + search + '%'
- }
+ Object.assign(followWhere, {
+ [Op.or]: [
+ searchAttribute(options.search, '$ActorFollowing.preferredUsername$'),
+ searchAttribute(options.search, '$ActorFollowing.Server.host$')
+ ]
})
}
include: [
{
model: ServerModel,
- required: true,
- where: followingServerWhere
+ required: true
}
]
}
const followWhere = state ? { state } : {}
const followerWhere: WhereOptions = {}
- const followerServerWhere: WhereOptions = {}
if (search) {
- Object.assign(followerServerWhere, {
- host: {
- [Op.iLike]: '%' + search + '%'
- }
+ Object.assign(followWhere, {
+ [Op.or]: [
+ searchAttribute(search, '$ActorFollower.preferredUsername$'),
+ searchAttribute(search, '$ActorFollower.Server.host$')
+ ]
})
}
include: [
{
model: ServerModel,
- required: true,
- where: followerServerWhere
+ required: true
}
]
},
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
logger.info('Removing duplicated video file %s.', logIdentifier)
- videoFile.Video.removeFile(videoFile, true)
- .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
+ videoFile.Video.removeFileAndTorrent(videoFile, true)
+ .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
}
if (instance.videoStreamingPlaylistId) {
--- /dev/null
+export * from './query'
+export * from './update'
--- /dev/null
+import { BindOrReplacements, QueryTypes } from 'sequelize'
+import { sequelizeTypescript } from '@server/initializers/database'
+
+function doesExist (query: string, bind?: BindOrReplacements) {
+ const options = {
+ type: QueryTypes.SELECT as QueryTypes.SELECT,
+ bind,
+ raw: true
+ }
+
+ return sequelizeTypescript.query(query, options)
+ .then(results => results.length === 1)
+}
+
+export {
+ doesExist
+}
--- /dev/null
+import { QueryTypes, Transaction } from 'sequelize'
+import { sequelizeTypescript } from '@server/initializers/database'
+
+// Sequelize always skip the update if we only update updatedAt field
+function setAsUpdated (table: string, id: number, transaction?: Transaction) {
+ return sequelizeTypescript.query(
+ `UPDATE "${table}" SET "updatedAt" = :updatedAt WHERE id = :id`,
+ {
+ replacements: { table, id, updatedAt: new Date() },
+ type: QueryTypes.UPDATE,
+ transaction
+ }
+ )
+}
+
+export {
+ setAsUpdated
+}
import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
+import { uuidToShort } from '@server/helpers/uuid'
import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user'
import { AttributesOnly } from '@shared/core-utils'
import { UserNotification, UserNotificationType } from '../../../shared'
return {
id: video.id,
uuid: video.uuid,
+ shortUUID: uuidToShort(video.uuid),
name: video.name
}
}
? {
id: abuse.VideoCommentAbuse.VideoComment.Video.id,
name: abuse.VideoCommentAbuse.VideoComment.Video.name,
+ shortUUID: uuidToShort(abuse.VideoCommentAbuse.VideoComment.Video.uuid),
uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid
}
: undefined
return {
id: playlist.id,
type: playlist.type,
- playlistUrl: playlist.playlistUrl,
- segmentsSha256Url: playlist.segmentsSha256Url,
+ playlistUrl: playlist.getMasterPlaylistUrl(video),
+ segmentsSha256Url: playlist.getSha256SegmentsUrl(video),
redundancies,
files
}
type: 'Link',
name: 'sha256',
mediaType: 'application/json' as 'application/json',
- href: playlist.segmentsSha256Url
+ href: playlist.getSha256SegmentsUrl(video)
})
addVideoFilesInAPAcc(tag, video, playlist.VideoFiles || [])
url.push({
type: 'Link',
mediaType: 'application/x-mpegURL' as 'application/x-mpegURL',
- href: playlist.playlistUrl,
+ href: playlist.getMasterPlaylistUrl(video),
tag
})
}
}
getStreamingPlaylistAttributes () {
- let playlistKeys = [ 'id', 'playlistUrl', 'type' ]
+ let playlistKeys = [ 'id', 'playlistUrl', 'playlistFilename', 'type' ]
if (this.mode === 'get') {
playlistKeys = playlistKeys.concat([
'p2pMediaLoaderInfohashes',
'p2pMediaLoaderPeerVersion',
+ 'segmentsSha256Filename',
'segmentsSha256Url',
'videoId',
'createdAt',
import { Sequelize } from 'sequelize'
import validator from 'validator'
import { exists } from '@server/helpers/custom-validators/misc'
+import { WEBSERVER } from '@server/initializers/constants'
import { buildDirectionAndField, createSafeIn } from '@server/models/utils'
import { MUserAccountId, MUserId } from '@server/types/models'
import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models'
nsfw?: boolean
filter?: VideoFilter
+ host?: string
isLive?: boolean
categoryOneOf?: number[]
tagsOneOf?: string[]
tagsAllOf?: string[]
+ uuids?: string[]
+
withFiles?: boolean
accountId?: number
this.whereOnlyLocal()
}
+ if (options.host) {
+ this.whereHost(options.host)
+ }
+
if (options.accountId) {
this.whereAccountId(options.accountId)
}
this.whereTagsAllOf(options.tagsAllOf)
}
+ if (options.uuids) {
+ this.whereUUIDs(options.uuids)
+ }
+
if (options.nsfw === true) {
this.whereNSFW()
} else if (options.nsfw === false) {
this.and.push('"video"."remote" IS FALSE')
}
+ private whereHost (host: string) {
+ // Local instance
+ if (host === WEBSERVER.HOST) {
+ this.and.push('"accountActor"."serverId" IS NULL')
+ return
+ }
+
+ this.joins.push('INNER JOIN "server" ON "server"."id" = "accountActor"."serverId"')
+
+ this.and.push('"server"."host" = :host')
+ this.replacements.host = host
+ }
+
private whereAccountId (accountId: number) {
this.and.push('"account"."id" = :accountId')
this.replacements.accountId = accountId
private whereFollowerActorId (followerActorId: number, includeLocalVideos: boolean) {
let query =
'(' +
- ' EXISTS (' +
+ ' EXISTS (' + // Videos shared by actors we follow
' SELECT 1 FROM "videoShare" ' +
' INNER JOIN "actorFollow" "actorFollowShare" ON "actorFollowShare"."targetActorId" = "videoShare"."actorId" ' +
' AND "actorFollowShare"."actorId" = :followerActorId AND "actorFollowShare"."state" = \'accepted\' ' +
' WHERE "videoShare"."videoId" = "video"."id"' +
' )' +
' OR' +
- ' EXISTS (' +
+ ' EXISTS (' + // Videos published by accounts we follow
' SELECT 1 from "actorFollow" ' +
- ' WHERE "actorFollow"."targetActorId" = "videoChannel"."actorId" AND "actorFollow"."actorId" = :followerActorId ' +
+ ' WHERE "actorFollow"."targetActorId" = "account"."actorId" AND "actorFollow"."actorId" = :followerActorId ' +
' AND "actorFollow"."state" = \'accepted\'' +
' )'
)
}
+ private whereUUIDs (uuids: string[]) {
+ this.and.push('"video"."uuid" IN (' + createSafeIn(this.sequelize, uuids) + ')')
+ }
+
private whereCategoryOneOf (categoryOneOf: number[]) {
this.and.push('"video"."category" IN (:categoryOneOf)')
this.replacements.categoryOneOf = categoryOneOf
-import { FindOptions, Includeable, literal, Op, QueryTypes, ScopeOptions, Transaction } from 'sequelize'
+import { FindOptions, Includeable, literal, Op, QueryTypes, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
import {
AllowNull,
BeforeDestroy,
Table,
UpdatedAt
} from 'sequelize-typescript'
-import { setAsUpdated } from '@server/helpers/database-utils'
import { MAccountActor } from '@server/types/models'
-import { AttributesOnly } from '@shared/core-utils'
+import { AttributesOnly, pick } from '@shared/core-utils'
import { ActivityPubActor } from '../../../shared/models/activitypub'
import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos'
import {
import { ActorFollowModel } from '../actor/actor-follow'
import { ActorImageModel } from '../actor/actor-image'
import { ServerModel } from '../server/server'
+import { setAsUpdated } from '../shared'
import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoPlaylistModel } from './video-playlist'
type AvailableForListOptions = {
actorId: number
search?: string
+ host?: string
+ handles?: string[]
}
type AvailableWithStatsOptions = {
// Only list local channels OR channels that are on an instance followed by actorId
const inQueryInstanceFollow = buildServerIdsFollowedBy(options.actorId)
+ const whereActorAnd: WhereOptions[] = [
+ {
+ [Op.or]: [
+ {
+ serverId: null
+ },
+ {
+ serverId: {
+ [Op.in]: Sequelize.literal(inQueryInstanceFollow)
+ }
+ }
+ ]
+ }
+ ]
+
+ let serverRequired = false
+ let whereServer: WhereOptions
+
+ if (options.host && options.host !== WEBSERVER.HOST) {
+ serverRequired = true
+ whereServer = { host: options.host }
+ }
+
+ if (options.host === WEBSERVER.HOST) {
+ whereActorAnd.push({
+ serverId: null
+ })
+ }
+
+ let rootWhere: WhereOptions
+ if (options.handles) {
+ const or: WhereOptions[] = []
+
+ for (const handle of options.handles || []) {
+ const [ preferredUsername, host ] = handle.split('@')
+
+ if (!host) {
+ or.push({
+ '$Actor.preferredUsername$': preferredUsername,
+ '$Actor.serverId$': null
+ })
+ } else {
+ or.push({
+ '$Actor.preferredUsername$': preferredUsername,
+ '$Actor.Server.host$': host
+ })
+ }
+ }
+
+ rootWhere = {
+ [Op.or]: or
+ }
+ }
+
return {
+ where: rootWhere,
include: [
{
attributes: {
},
model: ActorModel,
where: {
- [Op.or]: [
- {
- serverId: null
- },
- {
- serverId: {
- [Op.in]: Sequelize.literal(inQueryInstanceFollow)
- }
- }
- ]
+ [Op.and]: whereActorAnd
},
include: [
+ {
+ model: ServerModel,
+ required: serverRequired,
+ where: whereServer
+ },
+ {
+ model: ActorImageModel,
+ as: 'Avatar',
+ required: false
+ },
{
model: ActorImageModel,
as: 'Banner',
}
}
- static listForApi (parameters: {
- actorId: number
- start: number
- count: number
- sort: string
- }) {
- const { actorId } = parameters
-
- const query = {
- offset: parameters.start,
- limit: parameters.count,
- order: getSort(parameters.sort)
- }
-
- return VideoChannelModel
- .scope({
- method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
- })
- .findAndCountAll(query)
- .then(({ rows, count }) => {
- return { total: count, data: rows }
- })
- }
-
static listLocalsForSitemap (sort: string): Promise<MChannelActor[]> {
const query = {
attributes: [ ],
.findAll(query)
}
- static searchForApi (options: {
- actorId: number
- search: string
+ static listForApi (parameters: Pick<AvailableForListOptions, 'actorId'> & {
start: number
count: number
sort: string
}) {
- const attributesInclude = []
- const escapedSearch = VideoChannelModel.sequelize.escape(options.search)
- const escapedLikeSearch = VideoChannelModel.sequelize.escape('%' + options.search + '%')
- attributesInclude.push(createSimilarityAttribute('VideoChannelModel.name', options.search))
+ const { actorId } = parameters
const query = {
- attributes: {
- include: attributesInclude
- },
- offset: options.start,
- limit: options.count,
- order: getSort(options.sort),
- where: {
+ offset: parameters.start,
+ limit: parameters.count,
+ order: getSort(parameters.sort)
+ }
+
+ return VideoChannelModel
+ .scope({
+ method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
+ })
+ .findAndCountAll(query)
+ .then(({ rows, count }) => {
+ return { total: count, data: rows }
+ })
+ }
+
+ static searchForApi (options: Pick<AvailableForListOptions, 'actorId' | 'search' | 'host' | 'handles'> & {
+ start: number
+ count: number
+ sort: string
+ }) {
+ let attributesInclude: any[] = [ literal('0 as similarity') ]
+ let where: WhereOptions
+
+ if (options.search) {
+ const escapedSearch = VideoChannelModel.sequelize.escape(options.search)
+ const escapedLikeSearch = VideoChannelModel.sequelize.escape('%' + options.search + '%')
+ attributesInclude = [ createSimilarityAttribute('VideoChannelModel.name', options.search) ]
+
+ where = {
[Op.or]: [
Sequelize.literal(
'lower(immutable_unaccent("VideoChannelModel"."name")) % lower(immutable_unaccent(' + escapedSearch + '))'
}
}
+ const query = {
+ attributes: {
+ include: attributesInclude
+ },
+ offset: options.start,
+ limit: options.count,
+ order: getSort(options.sort),
+ where
+ }
+
return VideoChannelModel
.scope({
- method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
+ method: [ ScopeNames.FOR_API, pick(options, [ 'actorId', 'host', 'handles' ]) as AvailableForListOptions ]
})
.findAndCountAll(query)
.then(({ rows, count }) => {
import { remove } from 'fs-extra'
import * as memoizee from 'memoizee'
import { join } from 'path'
-import { FindOptions, Op, QueryTypes, Transaction } from 'sequelize'
+import { FindOptions, Op, Transaction } from 'sequelize'
import {
AllowNull,
BelongsTo,
} from '../../initializers/constants'
import { MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '../../types/models/video/video-file'
import { VideoRedundancyModel } from '../redundancy/video-redundancy'
+import { doesExist } from '../shared'
import { parseAggregateResult, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
static doesInfohashExist (infoHash: string) {
const query = 'SELECT 1 FROM "videoFile" WHERE "infoHash" = $infoHash LIMIT 1'
- const options = {
- type: QueryTypes.SELECT as QueryTypes.SELECT,
- bind: { infoHash },
- raw: true
- }
- return VideoModel.sequelize.query(query, options)
- .then(results => results.length === 1)
+ return doesExist(query, { infoHash })
}
static async doesVideoExistForVideoFile (id: number, videoIdOrUUID: number | string) {
return !!videoFile
}
+ static async doesOwnedTorrentFileExist (filename: string) {
+ const query = 'SELECT 1 FROM "videoFile" ' +
+ 'LEFT JOIN "video" "webtorrent" ON "webtorrent"."id" = "videoFile"."videoId" AND "webtorrent"."remote" IS FALSE ' +
+ 'LEFT JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."id" = "videoFile"."videoStreamingPlaylistId" ' +
+ 'LEFT JOIN "video" "hlsVideo" ON "hlsVideo"."id" = "videoStreamingPlaylist"."videoId" AND "hlsVideo"."remote" IS FALSE ' +
+ 'WHERE "torrentFilename" = $filename AND ("hlsVideo"."id" IS NOT NULL OR "webtorrent"."id" IS NOT NULL) LIMIT 1'
+
+ return doesExist(query, { filename })
+ }
+
+ static async doesOwnedWebTorrentVideoFileExist (filename: string) {
+ const query = 'SELECT 1 FROM "videoFile" INNER JOIN "video" ON "video"."id" = "videoFile"."videoId" AND "video"."remote" IS FALSE ' +
+ 'WHERE "filename" = $filename LIMIT 1'
+
+ return doesExist(query, { filename })
+ }
+
+ static loadByFilename (filename: string) {
+ const query = {
+ where: {
+ filename
+ }
+ }
+
+ return VideoFileModel.findOne(query)
+ }
+
static loadWithVideoOrPlaylistByTorrentFilename (filename: string) {
const query = {
where: {
}
getFileDownloadUrl (video: MVideoWithHost) {
- const basePath = this.isHLS()
- ? STATIC_DOWNLOAD_PATHS.HLS_VIDEOS
- : STATIC_DOWNLOAD_PATHS.VIDEOS
- const path = join(basePath, this.filename)
+ const path = this.isHLS()
+ ? join(STATIC_DOWNLOAD_PATHS.HLS_VIDEOS, `${video.uuid}-${this.resolution}-fragmented${this.extname}`)
+ : join(STATIC_DOWNLOAD_PATHS.VIDEOS, `${video.uuid}-${this.resolution}${this.extname}`)
if (video.isOwned()) return WEBSERVER.URL + path
Table,
UpdatedAt
} from 'sequelize-typescript'
-import { setAsUpdated } from '@server/helpers/database-utils'
import { buildUUID, uuidToShort } from '@server/helpers/uuid'
import { MAccountId, MChannelId } from '@server/types/models'
-import { AttributesOnly } from '@shared/core-utils'
+import { AttributesOnly, buildPlaylistEmbedPath, buildPlaylistWatchPath, pick } from '@shared/core-utils'
import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object'
import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
} from '../../types/models/video/video-playlist'
import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account'
import { ActorModel } from '../actor/actor'
+import { setAsUpdated } from '../shared'
import {
buildServerIdsFollowedBy,
buildTrigramSearchIndex,
videoChannelId?: number
listMyPlaylists?: boolean
search?: string
+ host?: string
+ uuids?: string[]
withVideos?: boolean
}
]
},
[ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => {
+ const whereAnd: WhereOptions[] = []
+
+ const whereServer = options.host && options.host !== WEBSERVER.HOST
+ ? { host: options.host }
+ : undefined
+
let whereActor: WhereOptions = {}
- const whereAnd: WhereOptions[] = []
+ if (options.host === WEBSERVER.HOST) {
+ whereActor = {
+ [Op.and]: [ { serverId: null } ]
+ }
+ }
if (options.listMyPlaylists !== true) {
whereAnd.push({
})
}
- whereActor = {
- [Op.or]: whereActorOr
- }
+ Object.assign(whereActor, { [Op.or]: whereActorOr })
}
if (options.accountId) {
})
}
+ if (options.uuids) {
+ whereAnd.push({
+ uuid: {
+ [Op.in]: options.uuids
+ }
+ })
+ }
+
if (options.withVideos === true) {
whereAnd.push(
literal(`(${getVideoLengthSelect()}) != 0`)
)
}
- const attributesInclude = []
+ let attributesInclude: any[] = [ literal('0 as similarity') ]
if (options.search) {
const escapedSearch = VideoPlaylistModel.sequelize.escape(options.search)
const escapedLikeSearch = VideoPlaylistModel.sequelize.escape('%' + options.search + '%')
- attributesInclude.push(createSimilarityAttribute('VideoPlaylistModel.name', options.search))
+ attributesInclude = [ createSimilarityAttribute('VideoPlaylistModel.name', options.search) ]
whereAnd.push({
[Op.or]: [
include: [
{
model: AccountModel.scope({
- method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ]
+ method: [ AccountScopeNames.SUMMARY, { whereActor, whereServer } as SummaryOptions ]
}),
required: true
},
})
Thumbnail: ThumbnailModel
- static listForApi (options: {
- followerActorId: number
+ static listForApi (options: AvailableForListOptions & {
start: number
count: number
sort: string
- type?: VideoPlaylistType
- accountId?: number
- videoChannelId?: number
- listMyPlaylists?: boolean
- search?: string
- withVideos?: boolean // false by default
}) {
const query = {
offset: options.start,
method: [
ScopeNames.AVAILABLE_FOR_LIST,
{
- type: options.type,
- followerActorId: options.followerActorId,
- accountId: options.accountId,
- videoChannelId: options.videoChannelId,
- listMyPlaylists: options.listMyPlaylists,
- search: options.search,
+ ...pick(options, [ 'type', 'followerActorId', 'accountId', 'videoChannelId', 'listMyPlaylists', 'search', 'host', 'uuids' ]),
+
withVideos: options.withVideos || false
} as AvailableForListOptions
]
})
}
- static searchForApi (options: {
- followerActorId: number
+ static searchForApi (options: Pick<AvailableForListOptions, 'followerActorId' | 'search'| 'host'| 'uuids'> & {
start: number
count: number
sort: string
- search?: string
}) {
return VideoPlaylistModel.listForApi({
...options,
+
type: VideoPlaylistType.REGULAR,
listMyPlaylists: false,
withVideos: true
return join(STATIC_PATHS.THUMBNAILS, this.Thumbnail.filename)
}
- getWatchUrl () {
- return WEBSERVER.URL + '/w/p/' + this.uuid
+ getWatchStaticPath () {
+ return buildPlaylistWatchPath({ shortUUID: uuidToShort(this.uuid) })
}
getEmbedStaticPath () {
- return '/video-playlists/embed/' + this.uuid
+ return buildPlaylistEmbedPath(this)
}
static async getStats () {
import * as memoizee from 'memoizee'
import { join } from 'path'
-import { Op, QueryTypes } from 'sequelize'
+import { Op } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoFileModel } from '@server/models/video/video-file'
-import { MStreamingPlaylist } from '@server/types/models'
+import { MStreamingPlaylist, MVideo } from '@server/types/models'
+import { AttributesOnly } from '@shared/core-utils'
import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
import { sha1 } from '../../helpers/core-utils'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
import { isArrayOf } from '../../helpers/custom-validators/misc'
import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos'
-import { CONSTRAINTS_FIELDS, MEMOIZE_LENGTH, MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, STATIC_PATHS } from '../../initializers/constants'
+import {
+ CONSTRAINTS_FIELDS,
+ MEMOIZE_LENGTH,
+ MEMOIZE_TTL,
+ P2P_MEDIA_LOADER_PEER_VERSION,
+ STATIC_PATHS,
+ WEBSERVER
+} from '../../initializers/constants'
import { VideoRedundancyModel } from '../redundancy/video-redundancy'
+import { doesExist } from '../shared'
import { throwIfNotValid } from '../utils'
import { VideoModel } from './video'
-import { AttributesOnly } from '@shared/core-utils'
@Table({
tableName: 'videoStreamingPlaylist',
type: VideoStreamingPlaylistType
@AllowNull(false)
- @Is('PlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'playlist url'))
+ @Column
+ playlistFilename: string
+
+ @AllowNull(true)
+ @Is('PlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'playlist url', true))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max))
playlistUrl: string
p2pMediaLoaderPeerVersion: number
@AllowNull(false)
- @Is('VideoStreamingSegmentsSha256Url', value => throwIfNotValid(value, isActivityPubUrlValid, 'segments sha256 url'))
+ @Column
+ segmentsSha256Filename: string
+
+ @AllowNull(true)
+ @Is('VideoStreamingSegmentsSha256Url', value => throwIfNotValid(value, isActivityPubUrlValid, 'segments sha256 url', true))
@Column
segmentsSha256Url: string
static doesInfohashExist (infoHash: string) {
const query = 'SELECT 1 FROM "videoStreamingPlaylist" WHERE $infoHash = ANY("p2pMediaLoaderInfohashes") LIMIT 1'
- const options = {
- type: QueryTypes.SELECT as QueryTypes.SELECT,
- bind: { infoHash },
- raw: true
- }
- return VideoModel.sequelize.query<object>(query, options)
- .then(results => results.length === 1)
+ return doesExist(query, { infoHash })
}
static buildP2PMediaLoaderInfoHashes (playlistUrl: string, files: unknown[]) {
p2pMediaLoaderPeerVersion: {
[Op.ne]: P2P_MEDIA_LOADER_PEER_VERSION
}
- }
+ },
+ include: [
+ {
+ model: VideoModel.unscoped(),
+ required: true
+ }
+ ]
}
return VideoStreamingPlaylistModel.findAll(query)
return VideoStreamingPlaylistModel.findByPk(id, options)
}
- static loadHLSPlaylistByVideo (videoId: number) {
+ static loadHLSPlaylistByVideo (videoId: number): Promise<MStreamingPlaylist> {
const options = {
where: {
type: VideoStreamingPlaylistType.HLS,
return VideoStreamingPlaylistModel.findOne(options)
}
- static getHlsPlaylistFilename (resolution: number) {
- return resolution + '.m3u8'
- }
+ static async loadOrGenerate (video: MVideo) {
+ let playlist = await VideoStreamingPlaylistModel.loadHLSPlaylistByVideo(video.id)
+ if (!playlist) playlist = new VideoStreamingPlaylistModel()
- static getMasterHlsPlaylistFilename () {
- return 'master.m3u8'
+ return Object.assign(playlist, { videoId: video.id, Video: video })
}
- static getHlsSha256SegmentsFilename () {
- return 'segments-sha256.json'
- }
+ assignP2PMediaLoaderInfoHashes (video: MVideo, files: unknown[]) {
+ const masterPlaylistUrl = this.getMasterPlaylistUrl(video)
- static getHlsMasterPlaylistStaticPath (videoUUID: string) {
- return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getMasterHlsPlaylistFilename())
+ this.p2pMediaLoaderInfohashes = VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(masterPlaylistUrl, files)
}
- static getHlsPlaylistStaticPath (videoUUID: string, resolution: number) {
- return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution))
+ getMasterPlaylistUrl (video: MVideo) {
+ if (video.isOwned()) return WEBSERVER.URL + this.getMasterPlaylistStaticPath(video.uuid)
+
+ return this.playlistUrl
}
- static getHlsSha256SegmentsStaticPath (videoUUID: string, isLive: boolean) {
- if (isLive) return join('/live', 'segments-sha256', videoUUID)
+ getSha256SegmentsUrl (video: MVideo) {
+ if (video.isOwned()) return WEBSERVER.URL + this.getSha256SegmentsStaticPath(video.uuid, video.isLive)
- return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, videoUUID, VideoStreamingPlaylistModel.getHlsSha256SegmentsFilename())
+ return this.segmentsSha256Url
}
getStringType () {
return this.type === other.type &&
this.videoId === other.videoId
}
+
+ private getMasterPlaylistStaticPath (videoUUID: string) {
+ return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, videoUUID, this.playlistFilename)
+ }
+
+ private getSha256SegmentsStaticPath (videoUUID: string, isLive: boolean) {
+ if (isLive) return join('/live', 'segments-sha256', videoUUID)
+
+ return join(STATIC_PATHS.STREAMING_PLAYLISTS.HLS, videoUUID, this.segmentsSha256Filename)
+ }
}
Table,
UpdatedAt
} from 'sequelize-typescript'
-import { setAsUpdated } from '@server/helpers/database-utils'
import { buildNSFWFilter } from '@server/helpers/express-utils'
+import { uuidToShort } from '@server/helpers/uuid'
import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
import { LiveManager } from '@server/lib/live/live-manager'
import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths'
import { getServerActor } from '@server/models/application/application'
import { ModelCache } from '@server/models/model-cache'
-import { AttributesOnly } from '@shared/core-utils'
+import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils'
import { VideoFile } from '@shared/models/videos/video-file.model'
import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
import { VideoObject } from '../../../shared/models/activitypub/objects'
import { ServerModel } from '../server/server'
import { TrackerModel } from '../server/tracker'
import { VideoTrackerModel } from '../server/video-tracker'
+import { setAsUpdated } from '../shared'
import { UserModel } from '../user/user'
import { UserVideoHistoryModel } from '../user/user-video-history'
import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils'
// Remove physical files and torrents
instance.VideoFiles.forEach(file => {
- tasks.push(instance.removeFile(file))
- tasks.push(file.removeTorrent())
+ tasks.push(instance.removeFileAndTorrent(file))
})
// Remove playlists file
const trendingDays = options.sort.endsWith('trending')
? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
: undefined
- let trendingAlgorithm
+
+ let trendingAlgorithm: string
if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot'
if (options.sort.endsWith('best')) trendingAlgorithm = 'best'
: serverActor.id
const queryOptions = {
- start: options.start,
- count: options.count,
- sort: options.sort,
+ ...pick(options, [
+ 'start',
+ 'count',
+ 'sort',
+ 'nsfw',
+ 'isLive',
+ 'categoryOneOf',
+ 'licenceOneOf',
+ 'languageOneOf',
+ 'tagsOneOf',
+ 'tagsAllOf',
+ 'filter',
+ 'withFiles',
+ 'accountId',
+ 'videoChannelId',
+ 'videoPlaylistId',
+ 'includeLocalVideos',
+ 'user',
+ 'historyOfUser',
+ 'search'
+ ]),
+
followerActorId,
serverAccountId: serverActor.Account.id,
- nsfw: options.nsfw,
- isLive: options.isLive,
- categoryOneOf: options.categoryOneOf,
- licenceOneOf: options.licenceOneOf,
- languageOneOf: options.languageOneOf,
- tagsOneOf: options.tagsOneOf,
- tagsAllOf: options.tagsAllOf,
- filter: options.filter,
- withFiles: options.withFiles,
- accountId: options.accountId,
- videoChannelId: options.videoChannelId,
- videoPlaylistId: options.videoPlaylistId,
- includeLocalVideos: options.includeLocalVideos,
- user: options.user,
- historyOfUser: options.historyOfUser,
trendingDays,
- trendingAlgorithm,
- search: options.search
+ trendingAlgorithm
}
return VideoModel.getAvailableForApi(queryOptions, options.countVideos)
}
static async searchAndPopulateAccountAndServer (options: {
+ start: number
+ count: number
+ sort: string
includeLocalVideos: boolean
search?: string
- start?: number
- count?: number
- sort?: string
+ host?: string
startDate?: string // ISO 8601
endDate?: string // ISO 8601
originallyPublishedStartDate?: string
durationMax?: number // seconds
user?: MUserAccountId
filter?: VideoFilter
+ uuids?: string[]
}) {
const serverActor = await getServerActor()
const queryOptions = {
- followerActorId: serverActor.id,
- serverAccountId: serverActor.Account.id,
-
- includeLocalVideos: options.includeLocalVideos,
- nsfw: options.nsfw,
- isLive: options.isLive,
-
- categoryOneOf: options.categoryOneOf,
- licenceOneOf: options.licenceOneOf,
- languageOneOf: options.languageOneOf,
+ ...pick(options, [
+ 'includeLocalVideos',
+ 'nsfw',
+ 'isLive',
+ 'categoryOneOf',
+ 'licenceOneOf',
+ 'languageOneOf',
+ 'tagsOneOf',
+ 'tagsAllOf',
+ 'user',
+ 'filter',
+ 'host',
+ 'start',
+ 'count',
+ 'sort',
+ 'startDate',
+ 'endDate',
+ 'originallyPublishedStartDate',
+ 'originallyPublishedEndDate',
+ 'durationMin',
+ 'durationMax',
+ 'uuids',
+ 'search'
+ ]),
- tagsOneOf: options.tagsOneOf,
- tagsAllOf: options.tagsAllOf,
-
- user: options.user,
- filter: options.filter,
-
- start: options.start,
- count: options.count,
- sort: options.sort,
-
- startDate: options.startDate,
- endDate: options.endDate,
-
- originallyPublishedStartDate: options.originallyPublishedStartDate,
- originallyPublishedEndDate: options.originallyPublishedEndDate,
-
- durationMin: options.durationMin,
- durationMax: options.durationMax,
-
- search: options.search
+ followerActorId: serverActor.id,
+ serverAccountId: serverActor.Account.id
}
return VideoModel.getAvailableForApi(queryOptions)
}
getWatchStaticPath () {
- return '/w/' + this.uuid
+ return buildVideoWatchPath({ shortUUID: uuidToShort(this.uuid) })
}
getEmbedStaticPath () {
- return '/videos/embed/' + this.uuid
+ return buildVideoEmbedPath(this)
}
getMiniatureStaticPath () {
.concat(toAdd)
}
- removeFile (videoFile: MVideoFile, isRedundancy = false) {
+ removeFileAndTorrent (videoFile: MVideoFile, isRedundancy = false) {
const filePath = getVideoFilePath(this, videoFile, isRedundancy)
- return remove(filePath)
- .catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
+
+ const promises: Promise<any>[] = [ remove(filePath) ]
+ if (!isRedundancy) promises.push(videoFile.removeTorrent())
+
+ return Promise.all(promises)
}
async removeStreamingPlaylistFiles (streamingPlaylist: MStreamingPlaylist, isRedundancy = false) {
import * as chai from 'chai'
import {
cleanupTests,
- closeAllSequelize,
- deleteAll,
+ createMultipleServers,
doubleFollow,
- getCount,
- selectQuery,
- setVideoField,
- updateQuery,
- wait
-} from '../../../../shared/extra-utils'
-import { flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { addVideoCommentThread, getVideoCommentThreads } from '../../../../shared/extra-utils/videos/video-comments'
-import { getVideo, rateVideo, uploadVideoAndGetId } from '../../../../shared/extra-utils/videos/videos'
+ PeerTubeServer,
+ setAccessTokensToServers,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test AP cleaner', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID1: string
let videoUUID2: string
let videoUUID3: string
videos: { cleanup_remote_interactions: true }
}
}
- servers = await flushAndRunMultipleServers(3, config)
+ servers = await createMultipleServers(3, config)
// Get the access tokens
await setAccessTokensToServers(servers)
// Create 1 comment per video
// Update 1 remote URL and 1 local URL on
- videoUUID1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'server 1' })).uuid
- videoUUID2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'server 2' })).uuid
- videoUUID3 = (await uploadVideoAndGetId({ server: servers[2], videoName: 'server 3' })).uuid
+ videoUUID1 = (await servers[0].videos.quickUpload({ name: 'server 1' })).uuid
+ videoUUID2 = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
+ videoUUID3 = (await servers[2].videos.quickUpload({ name: 'server 3' })).uuid
videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ]
for (const server of servers) {
for (const uuid of videoUUIDs) {
- await rateVideo(server.url, server.accessToken, uuid, 'like')
- await addVideoCommentThread(server.url, server.accessToken, uuid, 'comment')
+ await server.videos.rate({ id: uuid, rating: 'like' })
+ await server.comments.createThread({ videoId: uuid, text: 'comment' })
}
}
it('Should have the correct likes', async function () {
for (const server of servers) {
for (const uuid of videoUUIDs) {
- const res = await getVideo(server.url, uuid)
- expect(res.body.likes).to.equal(3)
- expect(res.body.dislikes).to.equal(0)
+ const video = await server.videos.get({ id: uuid })
+
+ expect(video.likes).to.equal(3)
+ expect(video.dislikes).to.equal(0)
}
}
})
it('Should destroy server 3 internal likes and correctly clean them', async function () {
this.timeout(20000)
- await deleteAll(servers[2].internalServerNumber, 'accountVideoRate')
+ await servers[2].sql.deleteAll('accountVideoRate')
for (const uuid of videoUUIDs) {
- await setVideoField(servers[2].internalServerNumber, uuid, 'likes', '0')
+ await servers[2].sql.setVideoField(uuid, 'likes', '0')
}
await wait(5000)
// Updated rates of my video
{
- const res = await getVideo(servers[0].url, videoUUID1)
- expect(res.body.likes).to.equal(2)
- expect(res.body.dislikes).to.equal(0)
+ const video = await servers[0].videos.get({ id: videoUUID1 })
+ expect(video.likes).to.equal(2)
+ expect(video.dislikes).to.equal(0)
}
// Did not update rates of a remote video
{
- const res = await getVideo(servers[0].url, videoUUID2)
- expect(res.body.likes).to.equal(3)
- expect(res.body.dislikes).to.equal(0)
+ const video = await servers[0].videos.get({ id: videoUUID2 })
+ expect(video.likes).to.equal(3)
+ expect(video.dislikes).to.equal(0)
}
})
for (const server of servers) {
for (const uuid of videoUUIDs) {
- await rateVideo(server.url, server.accessToken, uuid, 'dislike')
+ await server.videos.rate({ id: uuid, rating: 'dislike' })
}
}
for (const server of servers) {
for (const uuid of videoUUIDs) {
- const res = await getVideo(server.url, uuid)
- expect(res.body.likes).to.equal(0)
- expect(res.body.dislikes).to.equal(3)
+ const video = await server.videos.get({ id: uuid })
+ expect(video.likes).to.equal(0)
+ expect(video.dislikes).to.equal(3)
}
}
})
it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
this.timeout(20000)
- await deleteAll(servers[2].internalServerNumber, 'accountVideoRate')
+ await servers[2].sql.deleteAll('accountVideoRate')
for (const uuid of videoUUIDs) {
- await setVideoField(servers[2].internalServerNumber, uuid, 'dislikes', '0')
+ await servers[2].sql.setVideoField(uuid, 'dislikes', '0')
}
await wait(5000)
// Updated rates of my video
{
- const res = await getVideo(servers[0].url, videoUUID1)
- expect(res.body.likes).to.equal(0)
- expect(res.body.dislikes).to.equal(2)
+ const video = await servers[0].videos.get({ id: videoUUID1 })
+ expect(video.likes).to.equal(0)
+ expect(video.dislikes).to.equal(2)
}
// Did not update rates of a remote video
{
- const res = await getVideo(servers[0].url, videoUUID2)
- expect(res.body.likes).to.equal(0)
- expect(res.body.dislikes).to.equal(3)
+ const video = await servers[0].videos.get({ id: videoUUID2 })
+ expect(video.likes).to.equal(0)
+ expect(video.dislikes).to.equal(3)
}
})
it('Should destroy server 3 internal shares and correctly clean them', async function () {
this.timeout(20000)
- const preCount = await getCount(servers[0].internalServerNumber, 'videoShare')
+ const preCount = await servers[0].sql.getCount('videoShare')
expect(preCount).to.equal(6)
- await deleteAll(servers[2].internalServerNumber, 'videoShare')
+ await servers[2].sql.deleteAll('videoShare')
await wait(5000)
await waitJobs(servers)
// Still 6 because we don't have remote shares on local videos
- const postCount = await getCount(servers[0].internalServerNumber, 'videoShare')
+ const postCount = await servers[0].sql.getCount('videoShare')
expect(postCount).to.equal(6)
})
this.timeout(20000)
{
- const res = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 5)
- expect(res.body.total).to.equal(3)
+ const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
+ expect(total).to.equal(3)
}
- await deleteAll(servers[2].internalServerNumber, 'videoComment')
+ await servers[2].sql.deleteAll('videoComment')
await wait(5000)
await waitJobs(servers)
{
- const res = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 5)
- expect(res.body.total).to.equal(2)
+ const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
+ expect(total).to.equal(2)
}
})
async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
`INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
- const res = await selectQuery(servers[0].internalServerNumber, query)
+ const res = await servers[0].sql.selectQuery(query)
for (const rate of res) {
const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
{
const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
- await updateQuery(servers[1].internalServerNumber, query)
+ await servers[1].sql.updateQuery(query)
await wait(5000)
await waitJobs(servers)
const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
`INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
- const res = await selectQuery(servers[0].internalServerNumber, query)
+ const res = await servers[0].sql.selectQuery(query)
for (const comment of res) {
const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
{
const query = `UPDATE "videoComment" SET url = url || 'kyle'`
- await updateQuery(servers[1].internalServerNumber, query)
+ await servers[1].sql.updateQuery(query)
await wait(5000)
await waitJobs(servers)
after(async function () {
await cleanupTests(servers)
-
- await closeAllSequelize(servers)
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoPlaylistPrivacy } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
cleanupTests,
- createVideoPlaylist,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
makeActivityPubGetRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- setDefaultVideoChannel,
- uploadVideoAndGetId
-} from '../../../../shared/extra-utils'
+ setDefaultVideoChannel
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test activitypub', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let video: { id: number, uuid: string, shortUUID: string }
let playlist: { id: number, uuid: string, shortUUID: string }
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
{
- video = await uploadVideoAndGetId({ server: servers[0], videoName: 'video' })
+ video = await servers[0].videos.quickUpload({ name: 'video' })
}
{
- const playlistAttrs = { displayName: 'playlist', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[0].videoChannel.id }
- const resCreate = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs })
- playlist = resCreate.body.videoPlaylist
+ const attributes = { displayName: 'playlist', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[0].store.channel.id }
+ playlist = await servers[0].playlists.create({ attributes })
}
await doubleFollow(servers[0], servers[1])
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import {
- cleanupTests,
- closeAllSequelize,
- createUser,
- doubleFollow,
- flushAndRunMultipleServers,
- getVideosListSort,
- ServerInfo,
- setAccessTokensToServers,
- setActorField,
- setVideoField,
- uploadVideo,
- userLogin,
- waitJobs
-} from '../../../../shared/extra-utils'
import * as chai from 'chai'
-import { Video } from '../../../../shared/models/videos'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
const expect = chai.expect
describe('Test ActivityPub fetcher', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
// ---------------------------------------------------------------
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
const user = { username: 'user1', password: 'password' }
for (const server of servers) {
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
}
- const userAccessToken = await userLogin(servers[0], user)
+ const userAccessToken = await servers[0].login.getAccessToken(user)
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video root' })
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'bad video root' })
- const badVideoUUID = res.body.video.uuid
- await uploadVideo(servers[0].url, userAccessToken, { name: 'video user' })
+ await servers[0].videos.upload({ attributes: { name: 'video root' } })
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'bad video root' } })
+ await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'video user' } })
{
const to = 'http://localhost:' + servers[0].port + '/accounts/user1'
const value = 'http://localhost:' + servers[1].port + '/accounts/user1'
- await setActorField(servers[0].internalServerNumber, to, 'url', value)
+ await servers[0].sql.setActorField(to, 'url', value)
}
{
- const value = 'http://localhost:' + servers[2].port + '/videos/watch/' + badVideoUUID
- await setVideoField(servers[0].internalServerNumber, badVideoUUID, 'url', value)
+ const value = 'http://localhost:' + servers[2].port + '/videos/watch/' + uuid
+ await servers[0].sql.setVideoField(uuid, 'url', value)
}
})
await waitJobs(servers)
{
- const res = await getVideosListSort(servers[0].url, 'createdAt')
- expect(res.body.total).to.equal(3)
+ const { total, data } = await servers[0].videos.list({ sort: 'createdAt' })
- const data: Video[] = res.body.data
+ expect(total).to.equal(3)
expect(data[0].name).to.equal('video root')
expect(data[1].name).to.equal('bad video root')
expect(data[2].name).to.equal('video user')
}
{
- const res = await getVideosListSort(servers[1].url, 'createdAt')
- expect(res.body.total).to.equal(1)
+ const { total, data } = await servers[1].videos.list({ sort: 'createdAt' })
- const data: Video[] = res.body.data
+ expect(total).to.equal(1)
expect(data[0].name).to.equal('video root')
}
})
this.timeout(20000)
await cleanupTests(servers)
-
- await closeAllSequelize(servers)
})
})
import 'mocha'
import { expect } from 'chai'
-import { buildRequestStub } from '../../../../shared/extra-utils/miscs/stubs'
-import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../../../helpers/peertube-crypto'
import { cloneDeep } from 'lodash'
+import { buildAbsoluteFixturePath, buildRequestStub } from '@shared/extra-utils'
import { buildSignedActivity } from '../../../helpers/activitypub'
-import { buildAbsoluteFixturePath } from '@shared/extra-utils'
+import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../../../helpers/peertube-crypto'
describe('Test activity pub helpers', function () {
describe('When checking the Linked Signature', function () {
import 'mocha'
import {
- cleanupTests, closeAllSequelize,
- createVideoPlaylist,
+ cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- generateUserAccessToken,
- getVideo,
- getVideoPlaylist,
killallServers,
- reRunServer,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- setActorField,
setDefaultVideoChannel,
- setPlaylistField,
- setVideoField,
- uploadVideo,
- uploadVideoAndGetId,
wait,
waitJobs
-} from '../../../../shared/extra-utils'
-import { getAccount } from '../../../../shared/extra-utils/users/accounts'
-import { VideoPlaylistPrivacy } from '../../../../shared/models/videos'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
describe('Test AP refresher', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID1: string
let videoUUID2: string
let videoUUID3: string
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: false } })
+ servers = await createMultipleServers(2, { transcoding: { enabled: false } })
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
{
- videoUUID1 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video1' })).uuid
- videoUUID2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video2' })).uuid
- videoUUID3 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video3' })).uuid
+ videoUUID1 = (await servers[1].videos.quickUpload({ name: 'video1' })).uuid
+ videoUUID2 = (await servers[1].videos.quickUpload({ name: 'video2' })).uuid
+ videoUUID3 = (await servers[1].videos.quickUpload({ name: 'video3' })).uuid
}
{
- const a1 = await generateUserAccessToken(servers[1], 'user1')
- await uploadVideo(servers[1].url, a1, { name: 'video4' })
+ const token1 = await servers[1].users.generateUserAndToken('user1')
+ await servers[1].videos.upload({ token: token1, attributes: { name: 'video4' } })
- const a2 = await generateUserAccessToken(servers[1], 'user2')
- await uploadVideo(servers[1].url, a2, { name: 'video5' })
+ const token2 = await servers[1].users.generateUserAndToken('user2')
+ await servers[1].videos.upload({ token: token2, attributes: { name: 'video5' } })
}
{
- const playlistAttrs = { displayName: 'playlist1', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id }
- const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs })
- playlistUUID1 = res.body.videoPlaylist.uuid
+ const attributes = { displayName: 'playlist1', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].store.channel.id }
+ const created = await servers[1].playlists.create({ attributes })
+ playlistUUID1 = created.uuid
}
{
- const playlistAttrs = { displayName: 'playlist2', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id }
- const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs })
- playlistUUID2 = res.body.videoPlaylist.uuid
+ const attributes = { displayName: 'playlist2', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].store.channel.id }
+ const created = await servers[1].playlists.create({ attributes })
+ playlistUUID2 = created.uuid
}
await doubleFollow(servers[0], servers[1])
await wait(10000)
// Change UUID so the remote server returns a 404
- await setVideoField(servers[1].internalServerNumber, videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f')
+ await servers[1].sql.setVideoField(videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f')
- await getVideo(servers[0].url, videoUUID1)
- await getVideo(servers[0].url, videoUUID2)
+ await servers[0].videos.get({ id: videoUUID1 })
+ await servers[0].videos.get({ id: videoUUID2 })
await waitJobs(servers)
- await getVideo(servers[0].url, videoUUID1, HttpStatusCode.NOT_FOUND_404)
- await getVideo(servers[0].url, videoUUID2, HttpStatusCode.OK_200)
+ await servers[0].videos.get({ id: videoUUID1, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await servers[0].videos.get({ id: videoUUID2 })
})
it('Should not update a remote video if the remote instance is down', async function () {
this.timeout(70000)
- killallServers([ servers[1] ])
+ await killallServers([ servers[1] ])
- await setVideoField(servers[1].internalServerNumber, videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e')
+ await servers[1].sql.setVideoField(videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e')
// Video will need a refresh
await wait(10000)
- await getVideo(servers[0].url, videoUUID3)
+ await servers[0].videos.get({ id: videoUUID3 })
// The refresh should fail
await waitJobs([ servers[0] ])
- await reRunServer(servers[1])
+ await servers[1].run()
- await getVideo(servers[0].url, videoUUID3, HttpStatusCode.OK_200)
+ await servers[0].videos.get({ id: videoUUID3 })
})
})
it('Should remove a deleted actor', async function () {
this.timeout(60000)
+ const command = servers[0].accounts
+
await wait(10000)
// Change actor name so the remote server returns a 404
const to = 'http://localhost:' + servers[1].port + '/accounts/user2'
- await setActorField(servers[1].internalServerNumber, to, 'preferredUsername', 'toto')
+ await servers[1].sql.setActorField(to, 'preferredUsername', 'toto')
- await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port)
- await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port)
+ await command.get({ accountName: 'user1@localhost:' + servers[1].port })
+ await command.get({ accountName: 'user2@localhost:' + servers[1].port })
await waitJobs(servers)
- await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, HttpStatusCode.OK_200)
- await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, HttpStatusCode.NOT_FOUND_404)
+ await command.get({ accountName: 'user1@localhost:' + servers[1].port, expectedStatus: HttpStatusCode.OK_200 })
+ await command.get({ accountName: 'user2@localhost:' + servers[1].port, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
})
await wait(10000)
// Change UUID so the remote server returns a 404
- await setPlaylistField(servers[1].internalServerNumber, playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e')
+ await servers[1].sql.setPlaylistField(playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e')
- await getVideoPlaylist(servers[0].url, playlistUUID1)
- await getVideoPlaylist(servers[0].url, playlistUUID2)
+ await servers[0].playlists.get({ playlistId: playlistUUID1 })
+ await servers[0].playlists.get({ playlistId: playlistUUID2 })
await waitJobs(servers)
- await getVideoPlaylist(servers[0].url, playlistUUID1, HttpStatusCode.OK_200)
- await getVideoPlaylist(servers[0].url, playlistUUID2, HttpStatusCode.NOT_FOUND_404)
+ await servers[0].playlists.get({ playlistId: playlistUUID1, expectedStatus: HttpStatusCode.OK_200 })
+ await servers[0].playlists.get({ playlistId: playlistUUID2, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
})
this.timeout(10000)
await cleanupTests(servers)
-
- await closeAllSequelize(servers)
})
})
import 'mocha'
import * as chai from 'chai'
+import { activityPubContextify, buildSignedActivity } from '@server/helpers/activitypub'
import { buildDigest } from '@server/helpers/peertube-crypto'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-import {
- buildAbsoluteFixturePath,
- cleanupTests,
- closeAllSequelize,
- flushAndRunMultipleServers,
- killallServers,
- reRunServer,
- ServerInfo,
- setActorField,
- wait
-} from '../../../../shared/extra-utils'
-import { makeFollowRequest, makePOSTAPRequest } from '../../../../shared/extra-utils/requests/activitypub'
-import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub'
-import { HTTP_SIGNATURE } from '../../../initializers/constants'
-import { buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils'
+import { HTTP_SIGNATURE } from '@server/initializers/constants'
+import { buildGlobalHeaders } from '@server/lib/job-queue/handlers/utils/activitypub-http-utils'
+import { buildAbsoluteFixturePath, cleanupTests, createMultipleServers, killallServers, PeerTubeServer, wait } from '@shared/extra-utils'
+import { makeFollowRequest, makePOSTAPRequest } from '@shared/extra-utils/requests/activitypub'
+import { HttpStatusCode } from '@shared/models'
const expect = chai.expect
-function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: string, privateKey: string) {
+function setKeysOfServer (onServer: PeerTubeServer, ofServer: PeerTubeServer, publicKey: string, privateKey: string) {
const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
return Promise.all([
- setActorField(onServer.internalServerNumber, url, 'publicKey', publicKey),
- setActorField(onServer.internalServerNumber, url, 'privateKey', privateKey)
+ onServer.sql.setActorField(url, 'publicKey', publicKey),
+ onServer.sql.setActorField(url, 'privateKey', privateKey)
])
}
-function setUpdatedAtOfServer (onServer: ServerInfo, ofServer: ServerInfo, updatedAt: string) {
+function setUpdatedAtOfServer (onServer: PeerTubeServer, ofServer: PeerTubeServer, updatedAt: string) {
const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
return Promise.all([
- setActorField(onServer.internalServerNumber, url, 'createdAt', updatedAt),
- setActorField(onServer.internalServerNumber, url, 'updatedAt', updatedAt)
+ onServer.sql.setActorField(url, 'createdAt', updatedAt),
+ onServer.sql.setActorField(url, 'updatedAt', updatedAt)
])
}
-function getAnnounceWithoutContext (server: ServerInfo) {
+function getAnnounceWithoutContext (server: PeerTubeServer) {
const json = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
const result: typeof json = {}
}
describe('Test ActivityPub security', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let url: string
const keys = require(buildAbsoluteFixturePath('./ap-json/peertube/keys.json'))
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
url = servers[0].url + '/inbox'
await setUpdatedAtOfServer(servers[0], servers[1], '2015-07-17 22:00:00+00')
// Invalid peertube actor cache
- killallServers([ servers[1] ])
- await reRunServer(servers[1])
+ await killallServers([ servers[1] ])
+ await servers[1].run()
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
const headers = buildGlobalHeaders(body)
this.timeout(10000)
await cleanupTests(servers)
-
- await closeAllSequelize(servers)
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { AbuseCreate, AbuseState } from '@shared/models'
import {
- addAbuseMessage,
+ AbusesCommand,
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- deleteAbuse,
- deleteAbuseMessage,
+ createSingleServer,
doubleFollow,
- flushAndRunServer,
- generateUserAccessToken,
- getAdminAbusesList,
- getVideoIdFromUUID,
- listAbuseMessages,
makeGetRequest,
makePostBodyRequest,
- reportAbuse,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateAbuse,
- uploadVideo,
- userLogin,
waitJobs
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { AbuseCreate, AbuseState, HttpStatusCode } from '@shared/models'
describe('Test abuses API validators', function () {
const basePath = '/api/v1/abuses/'
- let server: ServerInfo
+ let server: PeerTubeServer
- let userAccessToken = ''
- let userAccessToken2 = ''
+ let userToken = ''
+ let userToken2 = ''
let abuseId: number
let messageId: number
+ let command: AbusesCommand
+
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- const username = 'user1'
- const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
- userAccessToken = await userLogin(server, { username, password })
+ userToken = await server.users.generateUserAndToken('user_1')
+ userToken2 = await server.users.generateUserAndToken('user_2')
- {
- userAccessToken2 = await generateUserAccessToken(server, 'user_2')
- }
+ server.store.videoCreated = await server.videos.upload()
- const res = await uploadVideo(server.url, server.accessToken, {})
- server.video = res.body.video
+ command = server.abuses
})
describe('When listing abuses for admins', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
await makeGetRequest({
url: server.url,
path,
- token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ token: userToken,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
videoIs: 'deleted'
}
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, query, expectedStatus: HttpStatusCode.OK_200 })
})
})
const path = '/api/v1/users/me/abuses'
it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, userAccessToken)
+ await checkBadStartPagination(server.url, path, userToken)
})
it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, userAccessToken)
+ await checkBadCountPagination(server.url, path, userToken)
})
it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, userAccessToken)
+ await checkBadSortPagination(server.url, path, userToken)
})
it('Should fail with a non authenticated user', async function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
it('Should fail with a bad id filter', async function () {
- await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { id: 'toto' } })
+ await makeGetRequest({ url: server.url, path, token: userToken, query: { id: 'toto' } })
})
it('Should fail with a bad state filter', async function () {
- await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { state: 'toto' } })
- await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { state: 0 } })
+ await makeGetRequest({ url: server.url, path, token: userToken, query: { state: 'toto' } })
+ await makeGetRequest({ url: server.url, path, token: userToken, query: { state: 0 } })
})
it('Should succeed with the correct params', async function () {
state: 2
}
- await makeGetRequest({ url: server.url, path, token: userAccessToken, query, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, token: userToken, query, expectedStatus: HttpStatusCode.OK_200 })
})
})
it('Should fail with nothing', async function () {
const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should fail with a wrong video', async function () {
const fields = { video: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path: path, token: userToken, fields })
})
it('Should fail with an unknown video', async function () {
await makePostBodyRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should fail with a wrong comment', async function () {
const fields = { comment: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path: path, token: userToken, fields })
})
it('Should fail with an unknown comment', async function () {
await makePostBodyRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should fail with a wrong account', async function () {
const fields = { account: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path: path, token: userToken, fields })
})
it('Should fail with an unknown account', async function () {
await makePostBodyRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
await makePostBodyRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail with a non authenticated user', async function () {
- const fields = { video: { id: server.video.id }, reason: 'my super reason' }
+ const fields = { video: { id: server.store.videoCreated.id }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a reason too short', async function () {
- const fields = { video: { id: server.video.id }, reason: 'h' }
+ const fields = { video: { id: server.store.videoCreated.id }, reason: 'h' }
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should fail with a too big reason', async function () {
- const fields = { video: { id: server.video.id }, reason: 'super'.repeat(605) }
+ const fields = { video: { id: server.store.videoCreated.id }, reason: 'super'.repeat(605) }
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should succeed with the correct parameters (basic)', async function () {
- const fields: AbuseCreate = { video: { id: server.video.shortUUID }, reason: 'my super reason' }
+ const fields: AbuseCreate = { video: { id: server.store.videoCreated.shortUUID }, reason: 'my super reason' }
const res = await makePostBodyRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
abuseId = res.body.abuse.id
})
it('Should fail with a wrong predefined reason', async function () {
- const fields = { video: { id: server.video.id }, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
+ const fields = { video: server.store.videoCreated, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should fail with negative timestamps', async function () {
- const fields = { video: { id: server.video.id, startAt: -1 }, reason: 'my super reason' }
+ const fields = { video: { id: server.store.videoCreated.id, startAt: -1 }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should fail mith misordered startAt/endAt', async function () {
- const fields = { video: { id: server.video.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
+ const fields = { video: { id: server.store.videoCreated.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
})
it('Should succeed with the corret parameters (advanced)', async function () {
const fields: AbuseCreate = {
video: {
- id: server.video.id,
+ id: server.store.videoCreated.id,
startAt: 1,
endAt: 5
},
predefinedReasons: [ 'serverRules' ]
}
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('When updating an abuse', function () {
it('Should fail with a non authenticated user', async function () {
- await updateAbuse(server.url, 'blabla', abuseId, {}, HttpStatusCode.UNAUTHORIZED_401)
+ await command.update({ token: 'blabla', abuseId, body: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {
- await updateAbuse(server.url, userAccessToken, abuseId, {}, HttpStatusCode.FORBIDDEN_403)
+ await command.update({ token: userToken, abuseId, body: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad abuse id', async function () {
- await updateAbuse(server.url, server.accessToken, 45, {}, HttpStatusCode.NOT_FOUND_404)
+ await command.update({ abuseId: 45, body: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a bad state', async function () {
const body = { state: 5 }
- await updateAbuse(server.url, server.accessToken, abuseId, body, HttpStatusCode.BAD_REQUEST_400)
+ await command.update({ abuseId, body, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with a bad moderation comment', async function () {
const body = { moderationComment: 'b'.repeat(3001) }
- await updateAbuse(server.url, server.accessToken, abuseId, body, HttpStatusCode.BAD_REQUEST_400)
+ await command.update({ abuseId, body, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with the correct params', async function () {
const body = { state: AbuseState.ACCEPTED }
- await updateAbuse(server.url, server.accessToken, abuseId, body)
+ await command.update({ abuseId, body })
})
})
const message = 'my super message'
it('Should fail with an invalid abuse id', async function () {
- await addAbuseMessage(server.url, userAccessToken2, 888, message, HttpStatusCode.NOT_FOUND_404)
+ await command.addMessage({ token: userToken2, abuseId: 888, message, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a non authenticated user', async function () {
- await addAbuseMessage(server.url, 'fake_token', abuseId, message, HttpStatusCode.UNAUTHORIZED_401)
+ await command.addMessage({ token: 'fake_token', abuseId, message, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with an invalid logged in user', async function () {
- await addAbuseMessage(server.url, userAccessToken2, abuseId, message, HttpStatusCode.FORBIDDEN_403)
+ await command.addMessage({ token: userToken2, abuseId, message, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with an invalid message', async function () {
- await addAbuseMessage(server.url, userAccessToken, abuseId, 'a'.repeat(5000), HttpStatusCode.BAD_REQUEST_400)
+ await command.addMessage({ token: userToken, abuseId, message: 'a'.repeat(5000), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should suceed with the correct params', async function () {
- const res = await addAbuseMessage(server.url, userAccessToken, abuseId, message)
+ const res = await command.addMessage({ token: userToken, abuseId, message })
messageId = res.body.abuseMessage.id
})
})
describe('When listing abuse messages', function () {
it('Should fail with an invalid abuse id', async function () {
- await listAbuseMessages(server.url, userAccessToken, 888, HttpStatusCode.NOT_FOUND_404)
+ await command.listMessages({ token: userToken, abuseId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a non authenticated user', async function () {
- await listAbuseMessages(server.url, 'fake_token', abuseId, HttpStatusCode.UNAUTHORIZED_401)
+ await command.listMessages({ token: 'fake_token', abuseId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with an invalid logged in user', async function () {
- await listAbuseMessages(server.url, userAccessToken2, abuseId, HttpStatusCode.FORBIDDEN_403)
+ await command.listMessages({ token: userToken2, abuseId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should succeed with the correct params', async function () {
- await listAbuseMessages(server.url, userAccessToken, abuseId)
+ await command.listMessages({ token: userToken, abuseId })
})
})
describe('When deleting an abuse message', function () {
-
it('Should fail with an invalid abuse id', async function () {
- await deleteAbuseMessage(server.url, userAccessToken, 888, messageId, HttpStatusCode.NOT_FOUND_404)
+ await command.deleteMessage({ token: userToken, abuseId: 888, messageId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with an invalid message id', async function () {
- await deleteAbuseMessage(server.url, userAccessToken, abuseId, 888, HttpStatusCode.NOT_FOUND_404)
+ await command.deleteMessage({ token: userToken, abuseId, messageId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a non authenticated user', async function () {
- await deleteAbuseMessage(server.url, 'fake_token', abuseId, messageId, HttpStatusCode.UNAUTHORIZED_401)
+ await command.deleteMessage({ token: 'fake_token', abuseId, messageId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with an invalid logged in user', async function () {
- await deleteAbuseMessage(server.url, userAccessToken2, abuseId, messageId, HttpStatusCode.FORBIDDEN_403)
+ await command.deleteMessage({ token: userToken2, abuseId, messageId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should succeed with the correct params', async function () {
- await deleteAbuseMessage(server.url, userAccessToken, abuseId, messageId)
+ await command.deleteMessage({ token: userToken, abuseId, messageId })
})
})
describe('When deleting a video abuse', function () {
it('Should fail with a non authenticated user', async function () {
- await deleteAbuse(server.url, 'blabla', abuseId, HttpStatusCode.UNAUTHORIZED_401)
+ await command.delete({ token: 'blabla', abuseId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {
- await deleteAbuse(server.url, userAccessToken, abuseId, HttpStatusCode.FORBIDDEN_403)
+ await command.delete({ token: userToken, abuseId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad abuse id', async function () {
- await deleteAbuse(server.url, server.accessToken, 45, HttpStatusCode.NOT_FOUND_404)
+ await command.delete({ abuseId: 45, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct params', async function () {
- await deleteAbuse(server.url, server.accessToken, abuseId)
+ await command.delete({ abuseId })
})
})
describe('When trying to manage messages of a remote abuse', function () {
let remoteAbuseId: number
- let anotherServer: ServerInfo
+ let anotherServer: PeerTubeServer
before(async function () {
this.timeout(50000)
- anotherServer = await flushAndRunServer(2)
+ anotherServer = await createSingleServer(2)
await setAccessTokensToServers([ anotherServer ])
await doubleFollow(anotherServer, server)
- const server2VideoId = await getVideoIdFromUUID(anotherServer.url, server.video.uuid)
- await reportAbuse({
- url: anotherServer.url,
- token: anotherServer.accessToken,
- reason: 'remote server',
- videoId: server2VideoId
- })
+ const server2VideoId = await anotherServer.videos.getId({ uuid: server.store.videoCreated.uuid })
+ await anotherServer.abuses.report({ reason: 'remote server', videoId: server2VideoId })
await waitJobs([ server, anotherServer ])
- const res = await getAdminAbusesList({ url: server.url, token: server.accessToken, sort: '-createdAt' })
- remoteAbuseId = res.body.data[0].id
+ const body = await command.getAdminList({ sort: '-createdAt' })
+ remoteAbuseId = body.data[0].id
})
it('Should fail when listing abuse messages of a remote abuse', async function () {
- await listAbuseMessages(server.url, server.accessToken, remoteAbuseId, HttpStatusCode.BAD_REQUEST_400)
+ await command.listMessages({ abuseId: remoteAbuseId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail when creating abuse message of a remote abuse', async function () {
- await addAbuseMessage(server.url, server.accessToken, remoteAbuseId, 'message', HttpStatusCode.BAD_REQUEST_400)
+ await command.addMessage({ abuseId: remoteAbuseId, message: 'message', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../../shared/extra-utils'
import {
checkBadCountPagination,
checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { getAccount } from '../../../../shared/extra-utils/users/accounts'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ checkBadStartPagination,
+ cleanupTests,
+ createSingleServer,
+ PeerTubeServer
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test accounts API validators', function () {
const path = '/api/v1/accounts/'
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
})
describe('When listing accounts', function () {
})
describe('When getting an account', function () {
+
it('Should return 404 with a non existing name', async function () {
- await getAccount(server.url, 'arfaze', HttpStatusCode.NOT_FOUND_404)
+ await server.accounts.get({ accountName: 'arfaze', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
makeDeleteRequest,
makeGetRequest,
makePostBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test blocklist API validators', function () {
- let servers: ServerInfo[]
- let server: ServerInfo
+ let servers: PeerTubeServer[]
+ let server: PeerTubeServer
let userAccessToken: string
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
server = servers[0]
const user = { username: 'user1', password: 'password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ userAccessToken = await server.login.getAccessToken(user)
await doubleFollow(servers[0], servers[1])
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
fields: { accountName: 'user1' },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: server.accessToken,
path,
fields: { accountName: 'user2' },
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
token: server.accessToken,
path,
fields: { accountName: 'root' },
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
token: server.accessToken,
path,
fields: { accountName: 'user1' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeDeleteRequest({
url: server.url,
path: path + '/user1',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/user2',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/user1',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
fields: { host: 'localhost:9002' },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:9003' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:' + server.port },
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:' + servers[1].port },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeDeleteRequest({
url: server.url,
path: path + '/localhost:' + servers[1].port,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/localhost:9004',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/localhost:' + servers[1].port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
token: userAccessToken,
path,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path,
fields: { accountName: 'user1' },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: userAccessToken,
path,
fields: { accountName: 'user1' },
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
token: server.accessToken,
path,
fields: { accountName: 'user2' },
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
token: server.accessToken,
path,
fields: { accountName: 'root' },
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
token: server.accessToken,
path,
fields: { accountName: 'user1' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeDeleteRequest({
url: server.url,
path: path + '/user1',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/user1',
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/user2',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/user1',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
token: userAccessToken,
path,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path,
fields: { host: 'localhost:' + servers[1].port },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: userAccessToken,
path,
fields: { host: 'localhost:' + servers[1].port },
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:9003' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:' + server.port },
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
token: server.accessToken,
path,
fields: { host: 'localhost:' + servers[1].port },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeDeleteRequest({
url: server.url,
path: path + '/localhost:' + servers[1].port,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/localhost:' + servers[1].port,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/localhost:9004',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/localhost:' + servers[1].port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import {
- cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import { makePostBodyRequest } from '../../../../shared/extra-utils/requests/requests'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test bulk API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
const user = { username: 'user1', password: 'password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When removing comments of', function () {
url: server.url,
path,
fields: { accountName: 'user1', scope: 'my-videos' },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: server.accessToken,
path,
fields: { accountName: 'user2', scope: 'my-videos' },
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
token: server.accessToken,
path,
fields: { accountName: 'user1', scope: 'my-videoss' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
token: userAccessToken,
path,
fields: { accountName: 'user1', scope: 'instance' },
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
token: server.accessToken,
path,
fields: { accountName: 'user1', scope: 'instance' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { omit } from 'lodash'
import 'mocha'
-import { CustomConfig } from '../../../../shared/models/server/custom-config.model'
-
+import { omit } from 'lodash'
import {
cleanupTests,
- createUser,
- flushAndRunServer,
- immutableAssign,
+ createSingleServer,
makeDeleteRequest,
makeGetRequest,
makePutBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { CustomConfig, HttpStatusCode } from '@shared/models'
describe('Test config API validators', function () {
const path = '/api/v1/config/custom'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
const updateParams: CustomConfig = {
instance: {
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
username: 'user1',
password: 'password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When getting the configuration', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
url: server.url,
path,
fields: updateParams,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
fields: updateParams,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
path,
fields: newUpdateParams,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail with a bad default NSFW policy', async function () {
- const newUpdateParams = immutableAssign(updateParams, {
+ const newUpdateParams = {
+ ...updateParams,
+
instance: {
defaultNSFWPolicy: 'hello'
}
- })
+ }
await makePutBodyRequest({
url: server.url,
path,
fields: newUpdateParams,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail if email disabled and signup requires email verification', async function () {
// opposite scenario - success when enable enabled - covered via tests/api/users/user-verification.ts
- const newUpdateParams = immutableAssign(updateParams, {
+ const newUpdateParams = {
+ ...updateParams,
+
signup: {
enabled: true,
limit: 5,
requiresEmailVerification: true
}
- })
+ }
await makePutBodyRequest({
url: server.url,
path,
fields: newUpdateParams,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail with a disabled webtorrent & hls transcoding', async function () {
- const newUpdateParams = immutableAssign(updateParams, {
+ const newUpdateParams = {
+ ...updateParams,
+
transcoding: {
hls: {
enabled: false
enabled: false
}
}
- })
+ }
await makePutBodyRequest({
url: server.url,
path,
fields: newUpdateParams,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
fields: updateParams,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
await makeDeleteRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils'
-import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, killallServers, MockSmtpServer, PeerTubeServer } from '@shared/extra-utils'
+import { ContactFormCommand } from '@shared/extra-utils/server'
+import { HttpStatusCode } from '@shared/models'
describe('Test contact form API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
const emails: object[] = []
const defaultBody = {
fromName: 'super name',
body: 'Hello, how are you?'
}
let emailPort: number
+ let command: ContactFormCommand
// ---------------------------------------------------------------
emailPort = await MockSmtpServer.Instance.collectEmails(emails)
// Email is disabled
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
+ command = server.contactForm
})
it('Should not accept a contact form if emails are disabled', async function () {
- await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
+ await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
})
it('Should not accept a contact form if it is disabled in the configuration', async function () {
this.timeout(10000)
- killallServers([ server ])
+ await killallServers([ server ])
// Contact form is disabled
- await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
- await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
+ await server.run({ smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
+ await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
})
it('Should not accept a contact form if from email is invalid', async function () {
this.timeout(10000)
- killallServers([ server ])
+ await killallServers([ server ])
// Email & contact form enabled
- await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
-
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromEmail: 'badEmail'
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromEmail: 'badEmail@'
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromEmail: undefined
- }))
+ await server.run({ smtp: { hostname: 'localhost', port: emailPort } })
+
+ await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, fromEmail: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not accept a contact form if from name is invalid', async function () {
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromName: 'name'.repeat(100)
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromName: ''
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- fromName: undefined
- }))
+ await command.send({ ...defaultBody, fromName: 'name'.repeat(100), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, fromName: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, fromName: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not accept a contact form if body is invalid', async function () {
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- body: 'body'.repeat(5000)
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- body: 'a'
- }))
- await sendContactForm(immutableAssign(defaultBody, {
- url: server.url,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- body: undefined
- }))
+ await command.send({ ...defaultBody, body: 'body'.repeat(5000), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, body: 'a', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.send({ ...defaultBody, body: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should accept a contact form with the correct parameters', async function () {
- await sendContactForm(immutableAssign(defaultBody, { url: server.url }))
+ await command.send(defaultBody)
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import { makeGetRequest, makePutBodyRequest } from '../../../../shared/extra-utils/requests/requests'
+ createSingleServer,
+ makeGetRequest,
+ makePutBodyRequest,
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test custom pages validators', function () {
const path = '/api/v1/custom-pages/homepage/instance'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
const user = { username: 'user1', password: 'password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When updating instance homepage', function () {
url: server.url,
path,
fields: { content: 'super content' },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: userAccessToken,
fields: { content: 'super content' },
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
path,
token: server.accessToken,
fields: { content: 'super content' },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import {
- cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import { makeGetRequest } from '../../../../shared/extra-utils/requests/requests'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test debug API validators', function () {
const path = '/api/v1/server/debug'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
username: 'user1',
password: 'my super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When getting debug endpoint', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
path,
token: server.accessToken,
query: { startDate: new Date().toISOString() },
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import {
- cleanupTests,
- createUser,
- flushAndRunServer,
- makeDeleteRequest, makeGetRequest,
- makePostBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
import {
checkBadCountPagination,
checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ checkBadStartPagination,
+ cleanupTests,
+ createSingleServer,
+ makeDeleteRequest,
+ makeGetRequest,
+ makePostBodyRequest,
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test server follows API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
let userAccessToken = null
before(async function () {
- const user = {
- username: 'user1',
- password: 'password'
- }
-
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ userAccessToken = await server.users.generateUserAndToken('user1')
})
describe('When adding follows', function () {
const path = '/api/v1/server/following'
- it('Should fail without hosts', async function () {
+ it('Should fail with nothing', async function () {
await makePostBodyRequest({
url: server.url,
path,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
- it('Should fail if hosts is not an array', async function () {
+ it('Should fail if hosts is not composed by hosts', async function () {
await makePostBodyRequest({
url: server.url,
path,
+ fields: { hosts: [ 'localhost:9002', 'localhost:coucou' ] },
token: server.accessToken,
- fields: { hosts: 'localhost:9002' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
- it('Should fail if the array is not composed by hosts', async function () {
+ it('Should fail if hosts is composed with http schemes', async function () {
await makePostBodyRequest({
url: server.url,
path,
- fields: { hosts: [ 'localhost:9002', 'localhost:coucou' ] },
+ fields: { hosts: [ 'localhost:9002', 'http://localhost:9003' ] },
+ token: server.accessToken,
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
+ })
+ })
+
+ it('Should fail if hosts are not unique', async function () {
+ await makePostBodyRequest({
+ url: server.url,
+ path,
+ fields: { urls: [ 'localhost:9002', 'localhost:9002' ] },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
- it('Should fail if the array is composed with http schemes', async function () {
+ it('Should fail if handles is not composed by handles', async function () {
await makePostBodyRequest({
url: server.url,
path,
- fields: { hosts: [ 'localhost:9002', 'http://localhost:9003' ] },
+ fields: { handles: [ 'hello@example.com', 'localhost:9001' ] },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
- it('Should fail if hosts are not unique', async function () {
+ it('Should fail if handles are not unique', async function () {
await makePostBodyRequest({
url: server.url,
path,
- fields: { urls: [ 'localhost:9002', 'localhost:9002' ] },
+ fields: { urls: [ 'hello@example.com', 'hello@example.com' ] },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
fields: { hosts: [ 'localhost:9002' ] },
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
fields: { hosts: [ 'localhost:9002' ] },
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.OK_200,
+ expectedStatus: HttpStatusCode.OK_200,
query: {
state: 'accepted',
actorType: 'Application'
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.OK_200,
+ expectedStatus: HttpStatusCode.OK_200,
query: {
state: 'accepted'
}
url: server.url,
path: path + '/toto@localhost:9002',
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/toto@localhost:9002',
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/toto',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
url: server.url,
path: path + '/toto@localhost:9003',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
})
url: server.url,
path: path + '/toto@localhost:9002/accept',
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/toto@localhost:9002/accept',
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/toto/accept',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
url: server.url,
path: path + '/toto@localhost:9003/accept',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
})
url: server.url,
path: path + '/toto@localhost:9002/reject',
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/toto@localhost:9002/reject',
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/toto/reject',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
url: server.url,
path: path + '/toto@localhost:9003/reject',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
})
url: server.url,
path: path + '/localhost:9002',
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/localhost:9002',
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: path + '/example.com',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import {
- cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
import {
checkBadCountPagination,
checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { makeGetRequest } from '../../../../shared/extra-utils/requests/requests'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ checkBadStartPagination,
+ cleanupTests,
+ createSingleServer,
+ makeGetRequest,
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test jobs API validators', function () {
const path = '/api/v1/jobs/failed'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
username: 'user1',
password: 'my super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When listing jobs', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
import 'mocha'
import { omit } from 'lodash'
-import { LiveVideo, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
buildAbsoluteFixturePath,
cleanupTests,
- createUser,
- flushAndRunServer,
- getLive,
- getMyUserInformation,
- immutableAssign,
+ createSingleServer,
+ LiveCommand,
makePostBodyRequest,
makeUploadRequest,
- runAndTestFfmpegStreamError,
+ PeerTubeServer,
sendRTMPStream,
- ServerInfo,
setAccessTokensToServers,
- stopFfmpeg,
- updateCustomSubConfig,
- updateLive,
- uploadVideoAndGetId,
- userLogin,
- waitUntilLivePublished
-} from '../../../../shared/extra-utils'
+ stopFfmpeg
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
describe('Test video lives API validator', function () {
const path = '/api/v1/videos/live'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
let channelId: number
let video: VideoCreateResult
let videoIdNotLive: number
+ let command: LiveCommand
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- maxInstanceLives: 20,
- maxUserLives: 20,
- allowReplay: true
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ maxInstanceLives: 20,
+ maxUserLives: 20,
+ allowReplay: true
+ }
}
})
const username = 'user1'
const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
- userAccessToken = await userLogin(server, { username, password })
+ await server.users.create({ username: username, password: password })
+ userAccessToken = await server.login.getAccessToken({ username, password })
{
- const res = await getMyUserInformation(server.url, server.accessToken)
- channelId = res.body.videoChannels[0].id
+ const { videoChannels } = await server.users.getMyInfo()
+ channelId = videoChannels[0].id
}
{
- videoIdNotLive = (await uploadVideoAndGetId({ server, videoName: 'not live' })).id
+ videoIdNotLive = (await server.videos.quickUpload({ name: 'not live' })).id
}
+
+ command = server.live
})
describe('When creating a live', function () {
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(65) })
+ const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad category', async function () {
- const fields = immutableAssign(baseCorrectParams, { category: 125 })
+ const fields = { ...baseCorrectParams, category: 125 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad licence', async function () {
- const fields = immutableAssign(baseCorrectParams, { licence: 125 })
+ const fields = { ...baseCorrectParams, licence: 125 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad language', async function () {
- const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
+ const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
})
it('Should fail with a bad channel', async function () {
- const fields = immutableAssign(baseCorrectParams, { channelId: 545454 })
+ const fields = { ...baseCorrectParams, channelId: 545454 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
username: 'fake',
password: 'fake_password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- const accessTokenUser = await userLogin(server, user)
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const customChannelId = res.body.videoChannels[0].id
+ const accessTokenUser = await server.login.getAccessToken(user)
+ const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
+ const customChannelId = videoChannels[0].id
- const fields = immutableAssign(baseCorrectParams, { channelId: customChannelId })
+ const fields = { ...baseCorrectParams, channelId: customChannelId }
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
})
it('Should fail with too many tags', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a tag length too low', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 't' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a tag length too big', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
})
it('Should fail with save replay and permanent live set to true', async function () {
- const fields = immutableAssign(baseCorrectParams, { saveReplay: true, permanentLive: true })
+ const fields = { ...baseCorrectParams, saveReplay: true, permanentLive: true }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
video = res.body.video
})
it('Should forbid if live is disabled', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: false
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: false
+ }
}
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should forbid to save replay if not enabled by the admin', async function () {
- const fields = immutableAssign(baseCorrectParams, { saveReplay: true })
-
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- allowReplay: false
+ const fields = { ...baseCorrectParams, saveReplay: true }
+
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: false
+ }
}
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should allow to save replay if enabled by the admin', async function () {
- const fields = immutableAssign(baseCorrectParams, { saveReplay: true })
-
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- allowReplay: true
+ const fields = { ...baseCorrectParams, saveReplay: true }
+
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true
+ }
}
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
it('Should not allow live if max instance lives is reached', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- maxInstanceLives: 1
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ maxInstanceLives: 1
+ }
}
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should not allow live if max user lives is reached', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- maxInstanceLives: 20,
- maxUserLives: 1
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ maxInstanceLives: 20,
+ maxUserLives: 1
+ }
}
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
describe('When getting live information', function () {
it('Should fail without access token', async function () {
- await getLive(server.url, '', video.id, HttpStatusCode.UNAUTHORIZED_401)
+ await command.get({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a bad access token', async function () {
- await getLive(server.url, 'toto', video.id, HttpStatusCode.UNAUTHORIZED_401)
+ await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with access token of another user', async function () {
- await getLive(server.url, userAccessToken, video.id, HttpStatusCode.FORBIDDEN_403)
+ await command.get({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad video id', async function () {
- await getLive(server.url, server.accessToken, 'toto', HttpStatusCode.BAD_REQUEST_400)
+ await command.get({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with an unknown video id', async function () {
- await getLive(server.url, server.accessToken, 454555, HttpStatusCode.NOT_FOUND_404)
+ await command.get({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a non live video', async function () {
- await getLive(server.url, server.accessToken, videoIdNotLive, HttpStatusCode.NOT_FOUND_404)
+ await command.get({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct params', async function () {
- await getLive(server.url, server.accessToken, video.id)
- await getLive(server.url, server.accessToken, video.shortUUID)
+ await command.get({ videoId: video.id })
+ await command.get({ videoId: video.uuid })
+ await command.get({ videoId: video.shortUUID })
})
})
describe('When updating live information', async function () {
it('Should fail without access token', async function () {
- await updateLive(server.url, '', video.id, {}, HttpStatusCode.UNAUTHORIZED_401)
+ await command.update({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a bad access token', async function () {
- await updateLive(server.url, 'toto', video.id, {}, HttpStatusCode.UNAUTHORIZED_401)
+ await command.update({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with access token of another user', async function () {
- await updateLive(server.url, userAccessToken, video.id, {}, HttpStatusCode.FORBIDDEN_403)
+ await command.update({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad video id', async function () {
- await updateLive(server.url, server.accessToken, 'toto', {}, HttpStatusCode.BAD_REQUEST_400)
+ await command.update({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with an unknown video id', async function () {
- await updateLive(server.url, server.accessToken, 454555, {}, HttpStatusCode.NOT_FOUND_404)
+ await command.update({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a non live video', async function () {
- await updateLive(server.url, server.accessToken, videoIdNotLive, {}, HttpStatusCode.NOT_FOUND_404)
+ await command.update({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with save replay and permanent live set to true', async function () {
const fields = { saveReplay: true, permanentLive: true }
- await updateLive(server.url, server.accessToken, video.id, fields, HttpStatusCode.BAD_REQUEST_400)
+ await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with the correct params', async function () {
- await updateLive(server.url, server.accessToken, video.id, { saveReplay: false })
- await updateLive(server.url, server.accessToken, video.shortUUID, { saveReplay: false })
+ await command.update({ videoId: video.id, fields: { saveReplay: false } })
+ await command.update({ videoId: video.uuid, fields: { saveReplay: false } })
+ await command.update({ videoId: video.shortUUID, fields: { saveReplay: false } })
})
it('Should fail to update replay status if replay is not allowed on the instance', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- live: {
- enabled: true,
- allowReplay: false
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: false
+ }
}
})
- await updateLive(server.url, server.accessToken, video.id, { saveReplay: true }, HttpStatusCode.FORBIDDEN_403)
+ await command.update({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail to update a live if it has already started', async function () {
this.timeout(40000)
- const resLive = await getLive(server.url, server.accessToken, video.id)
- const live: LiveVideo = resLive.body
+ const live = await command.get({ videoId: video.id })
- const command = sendRTMPStream(live.rtmpUrl, live.streamKey)
+ const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
- await waitUntilLivePublished(server.url, server.accessToken, video.id)
- await updateLive(server.url, server.accessToken, video.id, {}, HttpStatusCode.BAD_REQUEST_400)
+ await command.waitUntilPublished({ videoId: video.id })
+ await command.update({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
it('Should fail to stream twice in the save live', async function () {
this.timeout(40000)
- const resLive = await getLive(server.url, server.accessToken, video.id)
- const live: LiveVideo = resLive.body
+ const live = await command.get({ videoId: video.id })
- const command = sendRTMPStream(live.rtmpUrl, live.streamKey)
+ const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
- await waitUntilLivePublished(server.url, server.accessToken, video.id)
+ await command.waitUntilPublished({ videoId: video.id })
- await runAndTestFfmpegStreamError(server.url, server.accessToken, video.id, true)
+ await command.runAndTestStreamError({ videoId: video.id, shouldHaveError: true })
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
-import {
- cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import { makeGetRequest } from '../../../../shared/extra-utils/requests/requests'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test logs API validators', function () {
const path = '/api/v1/server/logs'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
username: 'user1',
password: 'my super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When getting logs', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
token: server.accessToken,
query: { startDate: 'toto' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
token: server.accessToken,
query: { startDate: new Date().toISOString(), endDate: 'toto' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
token: server.accessToken,
query: { startDate: new Date().toISOString(), level: 'toto' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
token: server.accessToken,
query: { startDate: new Date().toISOString() },
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { HttpStatusCode } from '@shared/core-utils'
import {
checkBadCountPagination,
checkBadSortPagination,
checkBadStartPagination,
cleanupTests,
- createUser,
- flushAndRunServer,
- immutableAssign,
- installPlugin,
+ createSingleServer,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
+ PeerTubeServer,
+ setAccessTokensToServers
} from '@shared/extra-utils'
-import { PeerTubePlugin, PluginType } from '@shared/models'
+import { HttpStatusCode, PeerTubePlugin, PluginType } from '@shared/models'
describe('Test server plugins API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = null
const npmPlugin = 'peertube-plugin-hello-world'
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
password: 'password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
{
- const res = await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: npmPlugin })
+ const res = await server.plugins.install({ npmName: npmPlugin })
const plugin = res.body as PeerTubePlugin
npmVersion = plugin.version
}
{
- const res = await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: themePlugin })
+ const res = await server.plugins.install({ npmName: themePlugin })
const plugin = res.body as PeerTubePlugin
themeVersion = plugin.version
}
]
for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
})
await makeGetRequest({
url: server.url,
path: '/themes/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
]
for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
})
]
for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
})
it('Should fail with an unknown auth name', async function () {
const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with an unknown static file', async function () {
]
for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
})
await makeGetRequest({
url: server.url,
path: '/themes/' + themeName + '/' + themeVersion + '/css/assets/fake.css',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
]
for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.OK_200 })
}
const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
- await makeGetRequest({ url: server.url, path: authPath, statusCodeExpected: HttpStatusCode.FOUND_302 })
+ await makeGetRequest({ url: server.url, path: authPath, expectedStatus: HttpStatusCode.FOUND_302 })
})
})
path,
token: 'fake_token',
query: baseQuery,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: userAccessToken,
query: baseQuery,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
it('Should fail with an invalid plugin type', async function () {
- const query = immutableAssign(baseQuery, { pluginType: 5 })
+ const query = { ...baseQuery, pluginType: 5 }
await makeGetRequest({
url: server.url,
})
it('Should fail with an invalid current peertube engine', async function () {
- const query = immutableAssign(baseQuery, { currentPeerTubeEngine: '1.0' })
+ const query = { ...baseQuery, currentPeerTubeEngine: '1.0' }
await makeGetRequest({
url: server.url,
path,
token: server.accessToken,
query: baseQuery,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
path,
token: 'fake_token',
query: baseQuery,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: userAccessToken,
query: baseQuery,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
it('Should fail with an invalid plugin type', async function () {
- const query = immutableAssign(baseQuery, { pluginType: 5 })
+ const query = { ...baseQuery, pluginType: 5 }
await makeGetRequest({
url: server.url,
path,
token: server.accessToken,
query: baseQuery,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
url: server.url,
path: path + suffix,
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
}
})
url: server.url,
path: path + suffix,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
}
})
url: server.url,
path: path + suffix,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
url: server.url,
path: path + suffix,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
})
url: server.url,
path: path + suffix,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
}
})
url: server.url,
path: path + suffix,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
}
})
path: path + npmPlugin + '/settings',
fields: { settings },
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path: path + npmPlugin + '/settings',
fields: { settings },
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
path: path + 'toto/settings',
fields: { settings },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makePutBodyRequest({
path: path + 'peertube-plugin-TOTO/settings',
fields: { settings },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path: path + 'peertube-plugin-toto/settings',
fields: { settings },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: path + npmPlugin + '/settings',
fields: { settings },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path: path + suffix,
fields: { npmName: npmPlugin },
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
}
})
path: path + suffix,
fields: { npmName: npmPlugin },
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
}
})
path: path + suffix,
fields: { npmName: 'toto' },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
path: path + suffix,
fields: { npmName: 'peertube-plugin-TOTO' },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
})
path: path + obj.suffix,
fields: { npmName: npmPlugin },
token: server.accessToken,
- statusCodeExpected: obj.status
+ expectedStatus: obj.status
})
}
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { VideoCreateResult } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
checkBadCountPagination,
checkBadSortPagination,
checkBadStartPagination,
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getVideo,
makeDeleteRequest,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideoAndGetId,
- userLogin,
waitJobs
-} from '../../../../shared/extra-utils'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoCreateResult } from '@shared/models'
describe('Test server redundancy API validators', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let userAccessToken = null
let videoIdLocal: number
let videoRemote: VideoCreateResult
before(async function () {
this.timeout(80000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
password: 'password'
}
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(servers[0], user)
+ await servers[0].users.create({ username: user.username, password: user.password })
+ userAccessToken = await servers[0].login.getAccessToken(user)
- videoIdLocal = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video' })).id
+ videoIdLocal = (await servers[0].videos.quickUpload({ name: 'video' })).id
- const remoteUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video' })).uuid
+ const remoteUUID = (await servers[1].videos.quickUpload({ name: 'video' })).uuid
await waitJobs(servers)
- const resVideo = await getVideo(servers[0].url, remoteUUID)
- videoRemote = resVideo.body
+ videoRemote = await servers[0].videos.get({ id: remoteUUID })
})
describe('When listing redundancies', function () {
})
it('Should fail with an invalid token', async function () {
- await makeGetRequest({ url, path, token: 'fake_token', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeGetRequest({ url, path, token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail if the user is not an administrator', async function () {
- await makeGetRequest({ url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makeGetRequest({ url, path, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad start pagination', async function () {
})
it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url, path, token, query: { target: 'my-videos' }, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url, path, token, query: { target: 'my-videos' }, expectedStatus: HttpStatusCode.OK_200 })
})
})
})
it('Should fail with an invalid token', async function () {
- await makePostBodyRequest({ url, path, token: 'fake_token', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePostBodyRequest({ url, path, token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail if the user is not an administrator', async function () {
- await makePostBodyRequest({ url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makePostBodyRequest({ url, path, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail without a video id', async function () {
})
it('Should fail with a not found video id', async function () {
- await makePostBodyRequest({ url, path, token, fields: { videoId: 6565 }, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makePostBodyRequest({ url, path, token, fields: { videoId: 6565 }, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a local a video id', async function () {
path,
token,
fields: { videoId: videoRemote.shortUUID },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
path,
token,
fields: { videoId: videoRemote.uuid },
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
})
})
it('Should fail with an invalid token', async function () {
- await makeDeleteRequest({ url, path: path + '1', token: 'fake_token', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeDeleteRequest({ url, path: path + '1', token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail if the user is not an administrator', async function () {
- await makeDeleteRequest({ url, path: path + '1', token: userAccessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makeDeleteRequest({ url, path: path + '1', token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with an incorrect video id', async function () {
})
it('Should fail with a not found video redundancy', async function () {
- await makeDeleteRequest({ url, path: path + '454545', token, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeDeleteRequest({ url, path: path + '454545', token, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
})
path: path + '/localhost:' + servers[1].port,
fields: { redundancyAllowed: true },
token: 'fake_token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path: path + '/localhost:' + servers[1].port,
fields: { redundancyAllowed: true },
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
path: path + '/example.com',
fields: { redundancyAllowed: true },
token: servers[0].accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: path + '/localhost:' + servers[1].port,
fields: { blabla: true },
token: servers[0].accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path: path + '/localhost:' + servers[1].port,
fields: { redundancyAllowed: true },
token: servers[0].accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
import 'mocha'
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- flushAndRunServer,
- immutableAssign,
+ createSingleServer,
makeGetRequest,
- ServerInfo,
- updateCustomSubConfig,
+ PeerTubeServer,
setAccessTokensToServers
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-
-function updateSearchIndex (server: ServerInfo, enabled: boolean, disableLocalSearch = false) {
- return updateCustomSubConfig(server.url, server.accessToken, {
- search: {
- searchIndex: {
- enabled,
- disableLocalSearch
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
+
+function updateSearchIndex (server: PeerTubeServer, enabled: boolean, disableLocalSearch = false) {
+ return server.config.updateCustomSubConfig({
+ newConfig: {
+ search: {
+ searchIndex: {
+ enabled,
+ disableLocalSearch
+ }
}
}
})
}
describe('Test videos API validator', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
await checkBadSortPagination(server.url, path, null, query)
})
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, statusCodeExpected: HttpStatusCode.OK_200 })
+ it('Should succeed with the correct parameters', async function () {
+ await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should fail with an invalid category', async function () {
- const customQuery1 = immutableAssign(query, { categoryOneOf: [ 'aa', 'b' ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery1 = { ...query, categoryOneOf: [ 'aa', 'b' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- const customQuery2 = immutableAssign(query, { categoryOneOf: 'a' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery2 = { ...query, categoryOneOf: 'a' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with a valid category', async function () {
- const customQuery1 = immutableAssign(query, { categoryOneOf: [ 1, 7 ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery1 = { ...query, categoryOneOf: [ 1, 7 ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery2 = immutableAssign(query, { categoryOneOf: 1 })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery2 = { ...query, categoryOneOf: 1 }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should fail with an invalid licence', async function () {
- const customQuery1 = immutableAssign(query, { licenceOneOf: [ 'aa', 'b' ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery1 = { ...query, licenceOneOf: [ 'aa', 'b' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- const customQuery2 = immutableAssign(query, { licenceOneOf: 'a' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery2 = { ...query, licenceOneOf: 'a' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with a valid licence', async function () {
- const customQuery1 = immutableAssign(query, { licenceOneOf: [ 1, 2 ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery1 = { ...query, licenceOneOf: [ 1, 2 ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery2 = immutableAssign(query, { licenceOneOf: 1 })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery2 = { ...query, licenceOneOf: 1 }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should succeed with a valid language', async function () {
- const customQuery1 = immutableAssign(query, { languageOneOf: [ 'fr', 'en' ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery1 = { ...query, languageOneOf: [ 'fr', 'en' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery2 = immutableAssign(query, { languageOneOf: 'fr' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery2 = { ...query, languageOneOf: 'fr' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should succeed with valid tags', async function () {
- const customQuery1 = immutableAssign(query, { tagsOneOf: [ 'tag1', 'tag2' ] })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery1 = { ...query, tagsOneOf: [ 'tag1', 'tag2' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery2 = immutableAssign(query, { tagsOneOf: 'tag1' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery2 = { ...query, tagsOneOf: 'tag1' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery3 = immutableAssign(query, { tagsAllOf: [ 'tag1', 'tag2' ] })
- await makeGetRequest({ url: server.url, path, query: customQuery3, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery3 = { ...query, tagsAllOf: [ 'tag1', 'tag2' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery3, expectedStatus: HttpStatusCode.OK_200 })
- const customQuery4 = immutableAssign(query, { tagsAllOf: 'tag1' })
- await makeGetRequest({ url: server.url, path, query: customQuery4, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery4 = { ...query, tagsAllOf: 'tag1' }
+ await makeGetRequest({ url: server.url, path, query: customQuery4, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should fail with invalid durations', async function () {
- const customQuery1 = immutableAssign(query, { durationMin: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery1 = { ...query, durationMin: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- const customQuery2 = immutableAssign(query, { durationMax: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery2 = { ...query, durationMax: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with invalid dates', async function () {
- const customQuery1 = immutableAssign(query, { startDate: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery1, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery1 = { ...query, startDate: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+
+ const customQuery2 = { ...query, endDate: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+
+ const customQuery3 = { ...query, originallyPublishedStartDate: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery3, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+
+ const customQuery4 = { ...query, originallyPublishedEndDate: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery4, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
+
+ it('Should fail with an invalid host', async function () {
+ const customQuery = { ...query, host: '6565' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
- const customQuery2 = immutableAssign(query, { endDate: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery2, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ it('Should succeed with a host', async function () {
+ const customQuery = { ...query, host: 'example.com' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
+ })
- const customQuery3 = immutableAssign(query, { originallyPublishedStartDate: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery3, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ it('Should fail with invalid uuids', async function () {
+ const customQuery = { ...query, uuids: [ '6565', 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
- const customQuery4 = immutableAssign(query, { originallyPublishedEndDate: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery4, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ it('Should succeed with valid uuids', async function () {
+ const customQuery = { ...query, uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
})
})
const path = '/api/v1/search/video-playlists/'
const query = {
- search: 'coucou'
+ search: 'coucou',
+ host: 'example.com'
}
it('Should fail with a bad start pagination', async function () {
await checkBadSortPagination(server.url, path, null, query)
})
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, statusCodeExpected: HttpStatusCode.OK_200 })
+ it('Should fail with an invalid host', async function () {
+ await makeGetRequest({ url: server.url, path, query: { ...query, host: '6565' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
+
+ it('Should fail with invalid uuids', async function () {
+ const customQuery = { ...query, uuids: [ '6565', 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
+
+ it('Should succeed with the correct parameters', async function () {
+ await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
})
})
const path = '/api/v1/search/video-channels/'
const query = {
- search: 'coucou'
+ search: 'coucou',
+ host: 'example.com'
}
it('Should fail with a bad start pagination', async function () {
await checkBadSortPagination(server.url, path, null, query)
})
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, statusCodeExpected: HttpStatusCode.OK_200 })
+ it('Should fail with an invalid host', async function () {
+ await makeGetRequest({ url: server.url, path, query: { ...query, host: '6565' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
+
+ it('Should fail with invalid handles', async function () {
+ await makeGetRequest({ url: server.url, path, query: { ...query, handles: [ '' ] }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ })
+
+ it('Should succeed with the correct parameters', async function () {
+ await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
})
})
for (const path of paths) {
{
- const customQuery = immutableAssign(query, { searchTarget: 'hello' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery = { ...query, searchTarget: 'hello' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
{
- const customQuery = immutableAssign(query, { searchTarget: undefined })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery = { ...query, searchTarget: undefined }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
}
{
- const customQuery = immutableAssign(query, { searchTarget: 'local' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery = { ...query, searchTarget: 'local' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
}
{
- const customQuery = immutableAssign(query, { searchTarget: 'search-index' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery = { ...query, searchTarget: 'search-index' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
await updateSearchIndex(server, true, true)
{
- const customQuery = immutableAssign(query, { searchTarget: 'local' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
+ const customQuery = { ...query, searchTarget: 'local' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
{
- const customQuery = immutableAssign(query, { searchTarget: 'search-index' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery = { ...query, searchTarget: 'search-index' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
}
await updateSearchIndex(server, true, false)
{
- const customQuery = immutableAssign(query, { searchTarget: 'local' })
- await makeGetRequest({ url: server.url, path, query: customQuery, statusCodeExpected: HttpStatusCode.OK_200 })
+ const customQuery = { ...query, searchTarget: 'local' }
+ await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
}
await updateSearchIndex(server, false, false)
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
import {
cleanupTests,
- flushAndRunServer,
+ createSingleServer,
makeGetRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo,
- createVideoPlaylist,
setDefaultVideoChannel
-} from '../../../../shared/extra-utils'
-import { VideoPlaylistPrivacy } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
describe('Test services API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let playlistUUID: string
// ---------------------------------------------------------------
before(async function () {
this.timeout(60000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
- {
- const res = await uploadVideo(server.url, server.accessToken, { name: 'my super name' })
- server.video = res.body.video
- }
+ server.store.videoCreated = await server.videos.upload({ attributes: { name: 'my super name' } })
{
- const res = await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ const created = await server.playlists.create({
+ attributes: {
displayName: 'super playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: server.store.channel.id
}
})
- playlistUUID = res.body.videoPlaylist.uuid
+ playlistUUID = created.uuid
}
})
})
it('Should fail with an invalid host', async function () {
- const embedUrl = 'http://hello.com/videos/watch/' + server.video.uuid
+ const embedUrl = 'http://hello.com/videos/watch/' + server.store.videoCreated.uuid
await checkParamEmbed(server, embedUrl)
})
})
it('Should fail with an invalid path', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watchs/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watchs/${server.store.videoCreated.uuid}`
await checkParamEmbed(server, embedUrl)
})
it('Should fail with an invalid max height', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watch/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxheight: 'hello' })
})
it('Should fail with an invalid max width', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watch/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxwidth: 'hello' })
})
it('Should fail with an invalid format', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watch/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { format: 'blabla' })
})
it('Should fail with a non supported format', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watch/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
await checkParamEmbed(server, embedUrl, HttpStatusCode.NOT_IMPLEMENTED_501, { format: 'xml' })
})
it('Should succeed with the correct params with a video', async function () {
- const embedUrl = `http://localhost:${server.port}/videos/watch/${server.video.uuid}`
+ const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
const query = {
format: 'json',
maxheight: 400,
})
})
-function checkParamEmbed (server: ServerInfo, embedUrl: string, statusCodeExpected = HttpStatusCode.BAD_REQUEST_400, query = {}) {
+function checkParamEmbed (server: PeerTubeServer, embedUrl: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400, query = {}) {
const path = '/services/oembed'
return makeGetRequest({
url: server.url,
path,
query: Object.assign(query, { url: embedUrl }),
- statusCodeExpected
+ expectedStatus
})
}
import 'mocha'
import { expect } from 'chai'
-import { HttpStatusCode, randomInt } from '@shared/core-utils'
-import { getGoodVideoUrl, getMagnetURI, getMyVideoImports, importVideo } from '@shared/extra-utils/videos/video-imports'
-import { MyUser, VideoImport, VideoImportState, VideoPrivacy } from '@shared/models'
+import { randomInt } from '@shared/core-utils'
import {
cleanupTests,
- flushAndRunServer,
- getMyUserInformation,
- immutableAssign,
- registerUser,
- ServerInfo,
+ createSingleServer,
+ FIXTURE_URLS,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateUser,
- uploadVideo,
- userLogin,
+ VideosCommand,
waitJobs
-} from '../../../../shared/extra-utils'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoImportState, VideoPrivacy } from '@shared/models'
describe('Test upload quota', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let rootId: number
+ let command: VideosCommand
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
- const res = await getMyUserInformation(server.url, server.accessToken)
- rootId = (res.body as MyUser).id
+ const user = await server.users.getMyInfo()
+ rootId = user.id
- await updateUser({
- url: server.url,
- userId: rootId,
- accessToken: server.accessToken,
- videoQuota: 42
- })
+ await server.users.update({ userId: rootId, videoQuota: 42 })
+
+ command = server.videos
})
describe('When having a video quota', function () {
this.timeout(30000)
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
- await registerUser(server.url, user.username, user.password)
- const userAccessToken = await userLogin(server, user)
+ await server.users.register(user)
+ const userToken = await server.login.getAccessToken(user)
- const videoAttributes = { fixture: 'video_short2.webm' }
+ const attributes = { fixture: 'video_short2.webm' }
for (let i = 0; i < 5; i++) {
- await uploadVideo(server.url, userAccessToken, videoAttributes)
+ await command.upload({ token: userToken, attributes })
}
- await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'legacy')
+ await command.upload({ token: userToken, attributes, expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
})
it('Should fail with a registered user having too many videos with resumable upload', async function () {
this.timeout(30000)
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
- await registerUser(server.url, user.username, user.password)
- const userAccessToken = await userLogin(server, user)
+ await server.users.register(user)
+ const userToken = await server.login.getAccessToken(user)
- const videoAttributes = { fixture: 'video_short2.webm' }
+ const attributes = { fixture: 'video_short2.webm' }
for (let i = 0; i < 5; i++) {
- await uploadVideo(server.url, userAccessToken, videoAttributes)
+ await command.upload({ token: userToken, attributes })
}
- await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'resumable')
+ await command.upload({ token: userToken, attributes, expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
})
it('Should fail to import with HTTP/Torrent/magnet', async function () {
this.timeout(120000)
const baseAttributes = {
- channelId: server.videoChannel.id,
+ channelId: server.store.channel.id,
privacy: VideoPrivacy.PUBLIC
}
- await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getGoodVideoUrl() }))
- await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
- await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' as any }))
+ await server.imports.importVideo({ attributes: { ...baseAttributes, targetUrl: FIXTURE_URLS.goodVideo } })
+ await server.imports.importVideo({ attributes: { ...baseAttributes, magnetUri: FIXTURE_URLS.magnet } })
+ await server.imports.importVideo({ attributes: { ...baseAttributes, torrentfile: 'video-720p.torrent' as any } })
await waitJobs([ server ])
- const res = await getMyVideoImports(server.url, server.accessToken)
+ const { total, data: videoImports } = await server.imports.getMyVideoImports()
+ expect(total).to.equal(3)
- expect(res.body.total).to.equal(3)
- const videoImports: VideoImport[] = res.body.data
expect(videoImports).to.have.lengthOf(3)
for (const videoImport of videoImports) {
describe('When having a daily video quota', function () {
it('Should fail with a user having too many videos daily', async function () {
- await updateUser({
- url: server.url,
- userId: rootId,
- accessToken: server.accessToken,
- videoQuotaDaily: 42
- })
+ await server.users.update({ userId: rootId, videoQuotaDaily: 42 })
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'legacy')
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'resumable')
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
})
})
describe('When having an absolute and daily video quota', function () {
it('Should fail if exceeding total quota', async function () {
- await updateUser({
- url: server.url,
+ await server.users.update({
userId: rootId,
- accessToken: server.accessToken,
videoQuota: 42,
videoQuotaDaily: 1024 * 1024 * 1024
})
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'legacy')
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'resumable')
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
})
it('Should fail if exceeding daily quota', async function () {
- await updateUser({
- url: server.url,
+ await server.users.update({
userId: rootId,
- accessToken: server.accessToken,
videoQuota: 1024 * 1024 * 1024,
videoQuotaDaily: 42
})
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'legacy')
- await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413, 'resumable')
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
+ await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
})
})
import 'mocha'
import { io } from 'socket.io-client'
-
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- flushAndRunServer,
- immutableAssign,
+ createSingleServer,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
wait
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { UserNotificationSetting, UserNotificationSettingValue } from '../../../../shared/models/users'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode, UserNotificationSetting, UserNotificationSettingValue } from '@shared/models'
describe('Test user notifications API validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
unread: 'toto'
},
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
ids: [ 'hello' ]
},
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makePostBodyRequest({
ids: [ ]
},
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makePostBodyRequest({
ids: 5
},
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
fields: {
ids: [ 5 ]
},
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
ids: [ 5 ]
},
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makePostBodyRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path,
token: server.accessToken,
fields: { newVideoFromSubscription: UserNotificationSettingValue.WEB },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail with incorrect field values', async function () {
{
- const fields = immutableAssign(correctFields, { newCommentOnMyVideo: 15 })
+ const fields = { ...correctFields, newCommentOnMyVideo: 15 }
await makePutBodyRequest({
url: server.url,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
{
- const fields = immutableAssign(correctFields, { newCommentOnMyVideo: 'toto' })
+ const fields = { ...correctFields, newCommentOnMyVideo: 'toto' }
await makePutBodyRequest({
url: server.url,
path,
fields,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
})
url: server.url,
path,
fields: correctFields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: server.accessToken,
fields: correctFields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- flushAndRunServer,
+ createSingleServer,
makeDeleteRequest,
makeGetRequest,
makePostBodyRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test user subscriptions API validators', function () {
const path = '/api/v1/users/me/subscriptions'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
username: 'user1',
password: 'my super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
describe('When listing my subscriptions', function () {
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
url: server.url,
path,
fields: { uri: 'user1_channel@localhost:' + server.port },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: server.accessToken,
fields: { uri: 'root' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makePostBodyRequest({
path,
token: server.accessToken,
fields: { uri: 'root@' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makePostBodyRequest({
path,
token: server.accessToken,
fields: { uri: 'root@hello@' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
token: server.accessToken,
fields: { uri: 'user1_channel@localhost:' + server.port },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
await waitJobs([ server ])
await makeGetRequest({
url: server.url,
path: path + '/user1_channel@localhost:' + server.port,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/root',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeGetRequest({
url: server.url,
path: path + '/root@',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeGetRequest({
url: server.url,
path: path + '/root@hello@',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
url: server.url,
path: path + '/root1@localhost:' + server.port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/user1_channel@localhost:' + server.port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
await makeGetRequest({
url: server.url,
path: existPath,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path: existPath,
query: { uris: 'toto' },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeGetRequest({
path: existPath,
query: { 'uris[]': 1 },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path: existPath,
query: { 'uris[]': 'coucou@localhost:' + server.port },
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
await makeDeleteRequest({
url: server.url,
path: path + '/user1_channel@localhost:' + server.port,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path: path + '/root',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeDeleteRequest({
url: server.url,
path: path + '/root@',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeDeleteRequest({
url: server.url,
path: path + '/root@hello@',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
url: server.url,
path: path + '/root1@localhost:' + server.port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: server.url,
path: path + '/user1_channel@localhost:' + server.port,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
import 'mocha'
import { omit } from 'lodash'
-import { User, UserRole, VideoCreateResult } from '../../../../shared'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoChannel,
- blockUser,
buildAbsoluteFixturePath,
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- deleteMe,
- flushAndRunServer,
- getMyUserInformation,
- getMyUserVideoRating,
- getUserScopedTokens,
- getUsersList,
- immutableAssign,
+ createSingleServer,
killallServers,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
makeUploadRequest,
- registerUser,
- removeUser,
- renewUserScopedTokens,
- reRunServer,
- ServerInfo,
+ MockSmtpServer,
+ PeerTubeServer,
setAccessTokensToServers,
- unblockUser,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
+ UsersCommand
+} from '@shared/extra-utils'
+import { HttpStatusCode, UserAdminFlag, UserRole, VideoCreateResult } from '@shared/models'
describe('Test users API validators', function () {
const path = '/api/v1/users/'
let rootId: number
let moderatorId: number
let video: VideoCreateResult
- let server: ServerInfo
- let serverWithRegistrationDisabled: ServerInfo
- let userAccessToken = ''
- let moderatorAccessToken = ''
+ let server: PeerTubeServer
+ let serverWithRegistrationDisabled: PeerTubeServer
+ let userToken = ''
+ let moderatorToken = ''
let emailPort: number
let overrideConfig: Object
{
const res = await Promise.all([
- flushAndRunServer(1, overrideConfig),
- flushAndRunServer(2)
+ createSingleServer(1, overrideConfig),
+ createSingleServer(2)
])
server = res[0]
}
{
- const user = {
- username: 'user1',
- password: 'my super password'
- }
-
- const videoQuota = 42000000
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: user.username,
- password: user.password,
- videoQuota: videoQuota
- })
- userAccessToken = await userLogin(server, user)
+ const user = { username: 'user1' }
+ await server.users.create({ ...user })
+ userToken = await server.login.getAccessToken(user)
}
{
- const moderator = {
- username: 'moderator1',
- password: 'super password'
- }
-
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: moderator.username,
- password: moderator.password,
- role: UserRole.MODERATOR
- })
-
- moderatorAccessToken = await userLogin(server, moderator)
+ const moderator = { username: 'moderator1' }
+ await server.users.create({ ...moderator, role: UserRole.MODERATOR })
+ moderatorToken = await server.login.getAccessToken(moderator)
}
{
- const moderator = {
- username: 'moderator2',
- password: 'super password'
- }
-
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: moderator.username,
- password: moderator.password,
- role: UserRole.MODERATOR
- })
+ const moderator = { username: 'moderator2' }
+ await server.users.create({ ...moderator, role: UserRole.MODERATOR })
}
{
- const res = await uploadVideo(server.url, server.accessToken, {})
- video = res.body.video
+ video = await server.videos.upload()
}
{
- const res = await getUsersList(server.url, server.accessToken)
- const users: User[] = res.body.data
-
- userId = users.find(u => u.username === 'user1').id
- rootId = users.find(u => u.username === 'root').id
- moderatorId = users.find(u => u.username === 'moderator2').id
+ const { data } = await server.users.list()
+ userId = data.find(u => u.username === 'user1').id
+ rootId = data.find(u => u.username === 'root').id
+ moderatorId = data.find(u => u.username === 'moderator2').id
}
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
await makeGetRequest({
url: server.url,
path,
- token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ token: userToken,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
}
it('Should fail with a too small username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: '' })
+ const fields = { ...baseCorrectParams, username: '' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a too long username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
+ const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a not lowercase username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
+ const fields = { ...baseCorrectParams, username: 'Toto' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with an incorrect username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
+ const fields = { ...baseCorrectParams, username: 'my username' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
})
it('Should fail with an invalid email', async function () {
- const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
+ const fields = { ...baseCorrectParams, email: 'test_example.com' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a too small password', async function () {
- const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
+ const fields = { ...baseCorrectParams, password: 'bla' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a too long password', async function () {
- const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
+ const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with empty password and no smtp configured', async function () {
- const fields = immutableAssign(baseCorrectParams, { password: '' })
+ const fields = { ...baseCorrectParams, password: '' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should succeed with no password on a server with smtp enabled', async function () {
this.timeout(20000)
- killallServers([ server ])
+ await killallServers([ server ])
+
+ const config = {
+ ...overrideConfig,
- const config = immutableAssign(overrideConfig, {
smtp: {
hostname: 'localhost',
port: emailPort
}
- })
- await reRunServer(server, config)
+ }
+ await server.run(config)
+
+ const fields = {
+ ...baseCorrectParams,
- const fields = immutableAssign(baseCorrectParams, {
password: '',
username: 'create_password',
email: 'create_password@example.com'
- })
+ }
await makePostBodyRequest({
url: server.url,
path: path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
it('Should fail with invalid admin flags', async function () {
- const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
+ const fields = { ...baseCorrectParams, adminFlags: 'toto' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
path,
token: 'super token',
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
it('Should fail if we add a user with the same username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
+ const fields = { ...baseCorrectParams, username: 'user1' }
await makePostBodyRequest({
url: server.url,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should fail if we add a user with the same email', async function () {
- const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
+ const fields = { ...baseCorrectParams, email: 'user1@example.com' }
await makePostBodyRequest({
url: server.url,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
})
it('Should fail with an invalid videoQuota', async function () {
- const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
+ const fields = { ...baseCorrectParams, videoQuota: -5 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with an invalid videoQuotaDaily', async function () {
- const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
+ const fields = { ...baseCorrectParams, videoQuotaDaily: -7 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
})
it('Should fail with an invalid user role', async function () {
- const fields = immutableAssign(baseCorrectParams, { role: 88989 })
+ const fields = { ...baseCorrectParams, role: 88989 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a "peertube" username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
+ const fields = { ...baseCorrectParams, username: 'peertube' }
await makePostBodyRequest({
url: server.url,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should fail to create a moderator or an admin with a moderator', async function () {
for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
- const fields = immutableAssign(baseCorrectParams, { role })
+ const fields = { ...baseCorrectParams, role }
await makePostBodyRequest({
url: server.url,
path,
- token: moderatorAccessToken,
+ token: moderatorToken,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
}
})
it('Should succeed to create a user with a moderator', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'a4656', email: 'a4656@example.com', role: UserRole.USER })
+ const fields = { ...baseCorrectParams, username: 'a4656', email: 'a4656@example.com', role: UserRole.USER }
await makePostBodyRequest({
url: server.url,
path,
- token: moderatorAccessToken,
+ token: moderatorToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
it('Should fail with a non admin user', async function () {
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- userAccessToken = await userLogin(server, user)
+ const user = { username: 'user1' }
+ userToken = await server.login.getAccessToken(user)
const fields = {
username: 'user3',
password: 'my super password',
videoQuota: 42000000
}
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
})
describe('When updating my account', function () {
+
it('Should fail with an invalid email attribute', async function () {
const fields = {
email: 'blabla'
it('Should fail with a too small password', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'bla'
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with a too long password', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'super'.repeat(61)
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail without the current password', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'super'.repeat(61)
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid current password', async function () {
await makePutBodyRequest({
url: server.url,
path: path + 'me',
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
nsfwPolicy: 'hello'
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid autoPlayVideo attribute', async function () {
autoPlayVideo: -1
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
autoPlayNextVideo: -1
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
videosHistoryEnabled: -1
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an non authenticated user', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'my super password'
}
path: path + 'me',
token: 'super token',
fields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
description: 'super'.repeat(201)
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid videoLanguages attribute', async function () {
videoLanguages: 'toto'
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
}
{
videoLanguages: languages
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
}
})
it('Should fail with an invalid theme', async function () {
const fields = { theme: 'invalid' }
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an unknown theme', async function () {
const fields = { theme: 'peertube-theme-unknown' }
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid noInstanceConfigWarningModal attribute', async function () {
noInstanceConfigWarningModal: -1
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid noWelcomeModal attribute', async function () {
noWelcomeModal: -1
}
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+ await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should succeed to change password with the correct params', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'my super password',
nsfwPolicy: 'blur',
autoPlayVideo: false,
await makePutBodyRequest({
url: server.url,
path: path + 'me',
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
await makePutBodyRequest({
url: server.url,
path: path + 'me',
- token: userAccessToken,
+ token: userToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path: path + '/me/avatar/pick',
fields,
attaches,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: server.accessToken,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
describe('When managing my scoped tokens', function () {
it('Should fail to get my scoped tokens with an non authenticated user', async function () {
- await getUserScopedTokens(server.url, null, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail to get my scoped tokens with a bad token', async function () {
- await getUserScopedTokens(server.url, 'bad', HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should succeed to get my scoped tokens', async function () {
- await getUserScopedTokens(server.url, server.accessToken)
+ await server.users.getMyScopedTokens()
})
it('Should fail to renew my scoped tokens with an non authenticated user', async function () {
- await renewUserScopedTokens(server.url, null, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.renewMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail to renew my scoped tokens with a bad token', async function () {
- await renewUserScopedTokens(server.url, 'bad', HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.renewMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should succeed to renew my scoped tokens', async function () {
- await renewUserScopedTokens(server.url, server.accessToken)
+ await server.users.renewMyScopedTokens()
})
})
url: server.url,
path: path + userId,
token: 'super token',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
it('Should fail with a non admin user', async function () {
- await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
})
})
it('Should fail with a too small password', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'bla'
}
it('Should fail with a too long password', async function () {
const fields = {
- currentPassword: 'my super password',
+ currentPassword: 'password',
password: 'super'.repeat(61)
}
path: path + userId,
token: 'super token',
fields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
await makePutBodyRequest({
url: server.url,
path: path + moderatorId,
- token: moderatorAccessToken,
+ token: moderatorToken,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
await makePutBodyRequest({
url: server.url,
path: path + userId,
- token: moderatorAccessToken,
+ token: moderatorToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
path: path + userId,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
describe('When getting my information', function () {
it('Should fail with a non authenticated user', async function () {
- await getMyUserInformation(server.url, 'fake_token', HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyInfo({ token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should success with the correct parameters', async function () {
- await getMyUserInformation(server.url, userAccessToken)
+ await server.users.getMyInfo({ token: userToken })
})
})
describe('When getting my video rating', function () {
+ let command: UsersCommand
+
+ before(function () {
+ command = server.users
+ })
+
it('Should fail with a non authenticated user', async function () {
- await getMyUserVideoRating(server.url, 'fake_token', video.id, HttpStatusCode.UNAUTHORIZED_401)
+ await command.getMyRating({ token: 'fake_token', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with an incorrect video uuid', async function () {
- await getMyUserVideoRating(server.url, server.accessToken, 'blabla', HttpStatusCode.BAD_REQUEST_400)
+ await command.getMyRating({ videoId: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with an unknown video', async function () {
- await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404)
+ await command.getMyRating({ videoId: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct parameters', async function () {
- await getMyUserVideoRating(server.url, server.accessToken, video.id)
- await getMyUserVideoRating(server.url, server.accessToken, video.uuid)
- await getMyUserVideoRating(server.url, server.accessToken, video.shortUUID)
+ await command.getMyRating({ videoId: video.id })
+ await command.getMyRating({ videoId: video.uuid })
+ await command.getMyRating({ videoId: video.shortUUID })
})
})
const path = '/api/v1/accounts/user1/ratings'
it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, userAccessToken)
+ await checkBadStartPagination(server.url, path, userToken)
})
it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, userAccessToken)
+ await checkBadCountPagination(server.url, path, userToken)
})
it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, userAccessToken)
+ await checkBadSortPagination(server.url, path, userToken)
})
it('Should fail with a unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a another user', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad type', async function () {
await makeGetRequest({
url: server.url,
path,
- token: userAccessToken,
+ token: userToken,
query: { rating: 'toto ' },
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('When blocking/unblocking/removing user', function () {
+
it('Should fail with an incorrect id', async function () {
- await removeUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
- await blockUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
- await unblockUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
+ const options = { userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
+
+ await server.users.remove(options)
+ await server.users.banUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.users.unbanUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with the root user', async function () {
- await removeUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
- await blockUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
- await unblockUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
+ const options = { userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
+
+ await server.users.remove(options)
+ await server.users.banUser(options)
+ await server.users.unbanUser(options)
})
it('Should return 404 with a non existing id', async function () {
- await removeUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
- await blockUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
- await unblockUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
+ const options = { userId: 4545454, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
+
+ await server.users.remove(options)
+ await server.users.banUser(options)
+ await server.users.unbanUser(options)
})
it('Should fail with a non admin user', async function () {
- await removeUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
- await blockUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
- await unblockUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
+ const options = { userId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
+
+ await server.users.remove(options)
+ await server.users.banUser(options)
+ await server.users.unbanUser(options)
})
it('Should fail on a moderator with a moderator', async function () {
- await removeUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
- await blockUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
- await unblockUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
+ const options = { userId: moderatorId, token: moderatorToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
+
+ await server.users.remove(options)
+ await server.users.banUser(options)
+ await server.users.unbanUser(options)
})
it('Should succeed on a user with a moderator', async function () {
- await blockUser(server.url, userId, moderatorAccessToken)
- await unblockUser(server.url, userId, moderatorAccessToken)
+ const options = { userId, token: moderatorToken }
+
+ await server.users.banUser(options)
+ await server.users.unbanUser(options)
})
})
describe('When deleting our account', function () {
it('Should fail with with the root account', async function () {
- await deleteMe(server.url, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
+ await server.users.deleteMe({ expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
})
}
it('Should fail with a too small username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: '' })
+ const fields = { ...baseCorrectParams, username: '' }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a too long username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
+ const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with an incorrect username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
+ const fields = { ...baseCorrectParams, username: 'my username' }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
})
it('Should fail with an invalid email', async function () {
- const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
+ const fields = { ...baseCorrectParams, email: 'test_example.com' }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a too small password', async function () {
- const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
+ const fields = { ...baseCorrectParams, password: 'bla' }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a too long password', async function () {
- const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
+ const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail if we register a user with the same username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'root' })
+ const fields = { ...baseCorrectParams, username: 'root' }
await makePostBodyRequest({
url: server.url,
path: registrationPath,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should fail with a "peertube" username', async function () {
- const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
+ const fields = { ...baseCorrectParams, username: 'peertube' }
await makePostBodyRequest({
url: server.url,
path: registrationPath,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should fail if we register a user with the same email', async function () {
- const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
+ const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' }
await makePostBodyRequest({
url: server.url,
path: registrationPath,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should fail with a bad display name', async function () {
- const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
+ const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a bad channel name', async function () {
- const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
+ const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a bad channel display name', async function () {
- const fields = immutableAssign(baseCorrectParams, { channel: { name: 'toto', displayName: '' } })
+ const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with a channel name that is the same as username', async function () {
const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
- const fields = immutableAssign(baseCorrectParams, source)
+ const fields = { ...baseCorrectParams, ...source }
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
})
it('Should fail with an existing channel', async function () {
- const videoChannelAttributesArg = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
- await addVideoChannel(server.url, server.accessToken, videoChannelAttributesArg)
+ const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
+ await server.channels.create({ attributes })
- const fields = immutableAssign(baseCorrectParams, { channel: { name: 'existing_channel', displayName: 'toto' } })
+ const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } }
await makePostBodyRequest({
url: server.url,
path: registrationPath,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should succeed with the correct params', async function () {
- const fields = immutableAssign(baseCorrectParams, { channel: { name: 'super_channel', displayName: 'toto' } })
+ const fields = { ...baseCorrectParams, channel: { name: 'super_channel', displayName: 'toto' } }
await makePostBodyRequest({
url: server.url,
path: registrationPath,
token: server.accessToken,
fields: fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
path: registrationPath,
token: serverWithRegistrationDisabled.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
})
describe('When registering multiple users on a server with users limit', function () {
it('Should fail when after 3 registrations', async function () {
- await registerUser(server.url, 'user42', 'super password', HttpStatusCode.FORBIDDEN_403)
+ await server.users.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-
+import { expect } from 'chai'
import {
+ BlacklistCommand,
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getBlacklistedVideosList,
- getVideo,
- getVideoWithToken,
makePostBodyRequest,
makePutBodyRequest,
- removeVideoFromBlacklist,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo,
- userLogin,
waitJobs
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { VideoBlacklistType, VideoDetails } from '../../../../shared/models/videos'
-import { expect } from 'chai'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoBlacklistType } from '@shared/models'
describe('Test video blacklist API validators', function () {
- let servers: ServerInfo[]
- let notBlacklistedVideoId: number
+ let servers: PeerTubeServer[]
+ let notBlacklistedVideoId: string
let remoteVideoUUID: string
let userAccessToken1 = ''
let userAccessToken2 = ''
+ let command: BlacklistCommand
// ---------------------------------------------------------------
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
{
const username = 'user1'
const password = 'my super password'
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: username, password: password })
- userAccessToken1 = await userLogin(servers[0], { username, password })
+ await servers[0].users.create({ username: username, password: password })
+ userAccessToken1 = await servers[0].login.getAccessToken({ username, password })
}
{
const username = 'user2'
const password = 'my super password'
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: username, password: password })
- userAccessToken2 = await userLogin(servers[0], { username, password })
+ await servers[0].users.create({ username: username, password: password })
+ userAccessToken2 = await servers[0].login.getAccessToken({ username, password })
}
{
- const res = await uploadVideo(servers[0].url, userAccessToken1, {})
- servers[0].video = res.body.video
+ servers[0].store.videoCreated = await servers[0].videos.upload({ token: userAccessToken1 })
}
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, {})
- notBlacklistedVideoId = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload()
+ notBlacklistedVideoId = uuid
}
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, {})
- remoteVideoUUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload()
+ remoteVideoUUID = uuid
}
await waitJobs(servers)
+
+ command = servers[0].blacklist
})
describe('When adding a video in blacklist', function () {
const basePath = '/api/v1/videos/'
it('Should fail with nothing', async function () {
- const path = basePath + servers[0].video + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated + '/blacklist'
const fields = {}
await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
})
})
it('Should fail with a non authenticated user', async function () {
- const path = basePath + servers[0].video + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated + '/blacklist'
const fields = {}
- await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {
- const path = basePath + servers[0].video + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated + '/blacklist'
const fields = {}
await makePostBodyRequest({
url: servers[0].url,
path,
token: userAccessToken2,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should fail with an invalid reason', async function () {
- const path = basePath + servers[0].video.uuid + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
const fields = { reason: 'a'.repeat(305) }
await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
path,
token: servers[0].accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should succeed with the correct params', async function () {
- const path = basePath + servers[0].video.uuid + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
const fields = {}
await makePostBodyRequest({
path,
token: servers[0].accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path,
token: servers[0].accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should fail with a non authenticated user', async function () {
- const path = basePath + servers[0].video + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated + '/blacklist'
const fields = {}
- await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {
- const path = basePath + servers[0].video + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated + '/blacklist'
const fields = {}
await makePutBodyRequest({
url: servers[0].url,
path,
token: userAccessToken2,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should fail with an invalid reason', async function () {
- const path = basePath + servers[0].video.uuid + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
const fields = { reason: 'a'.repeat(305) }
await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
})
it('Should succeed with the correct params', async function () {
- const path = basePath + servers[0].video.shortUUID + '/blacklist'
+ const path = basePath + servers[0].store.videoCreated.shortUUID + '/blacklist'
const fields = { reason: 'hello' }
await makePutBodyRequest({
path,
token: servers[0].accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
describe('When getting blacklisted video', function () {
it('Should fail with a non authenticated user', async function () {
- await getVideo(servers[0].url, servers[0].video.uuid, HttpStatusCode.UNAUTHORIZED_401)
+ await servers[0].videos.get({ id: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with another user', async function () {
- await getVideoWithToken(servers[0].url, userAccessToken2, servers[0].video.uuid, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].videos.getWithToken({
+ token: userAccessToken2,
+ id: servers[0].store.videoCreated.uuid,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should succeed with the owner authenticated user', async function () {
- const res = await getVideoWithToken(servers[0].url, userAccessToken1, servers[0].video.uuid, HttpStatusCode.OK_200)
- const video: VideoDetails = res.body
-
+ const video = await servers[0].videos.getWithToken({ token: userAccessToken1, id: servers[0].store.videoCreated.uuid })
expect(video.blacklisted).to.be.true
})
it('Should succeed with an admin', async function () {
- const video = servers[0].video
+ const video = servers[0].store.videoCreated
for (const id of [ video.id, video.uuid, video.shortUUID ]) {
- const res = await getVideoWithToken(servers[0].url, servers[0].accessToken, id, HttpStatusCode.OK_200)
- const video: VideoDetails = res.body
-
+ const video = await servers[0].videos.getWithToken({ id, expectedStatus: HttpStatusCode.OK_200 })
expect(video.blacklisted).to.be.true
}
})
})
describe('When removing a video in blacklist', function () {
+
it('Should fail with a non authenticated user', async function () {
- await removeVideoFromBlacklist(servers[0].url, 'fake token', servers[0].video.uuid, HttpStatusCode.UNAUTHORIZED_401)
+ await command.remove({
+ token: 'fake token',
+ videoId: servers[0].store.videoCreated.uuid,
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
+ })
})
it('Should fail with a non admin user', async function () {
- await removeVideoFromBlacklist(servers[0].url, userAccessToken2, servers[0].video.uuid, HttpStatusCode.FORBIDDEN_403)
+ await command.remove({
+ token: userAccessToken2,
+ videoId: servers[0].store.videoCreated.uuid,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should fail with an incorrect id', async function () {
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, 'hello', HttpStatusCode.BAD_REQUEST_400)
+ await command.remove({ videoId: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with a not blacklisted video', async function () {
// The video was not added to the blacklist so it should fail
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, notBlacklistedVideoId, HttpStatusCode.NOT_FOUND_404)
+ await command.remove({ videoId: notBlacklistedVideoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct params', async function () {
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, servers[0].video.uuid, HttpStatusCode.NO_CONTENT_204)
+ await command.remove({ videoId: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
})
})
const basePath = '/api/v1/videos/blacklist/'
it('Should fail with a non authenticated user', async function () {
- await getBlacklistedVideosList({ url: servers[0].url, token: 'fake token', specialStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await servers[0].blacklist.list({ token: 'fake token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {
- await getBlacklistedVideosList({ url: servers[0].url, token: userAccessToken2, specialStatus: HttpStatusCode.FORBIDDEN_403 })
+ await servers[0].blacklist.list({ token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a bad start pagination', async function () {
})
it('Should fail with an invalid type', async function () {
- await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- type: 0,
- specialStatus: HttpStatusCode.BAD_REQUEST_400
- })
+ await servers[0].blacklist.list({ type: 0, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with the correct parameters', async function () {
- await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, type: VideoBlacklistType.MANUAL })
+ await servers[0].blacklist.list({ type: VideoBlacklistType.MANUAL })
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { VideoCreateResult } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
buildAbsoluteFixturePath,
cleanupTests,
- createUser,
- flushAndRunServer,
+ createSingleServer,
makeDeleteRequest,
makeGetRequest,
makeUploadRequest,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import { createVideoCaption } from '../../../../shared/extra-utils/videos/video-captions'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoCreateResult } from '@shared/models'
describe('Test video captions API validator', function () {
const path = '/api/v1/videos/'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
let video: VideoCreateResult
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- {
- const res = await uploadVideo(server.url, server.accessToken, {})
- video = res.body.video
- }
+ video = await server.videos.upload()
{
const user = {
username: 'user1',
password: 'my super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
}
})
token: server.accessToken,
fields,
attaches,
- statusCodeExpected: 404
+ expectedStatus: 404
})
})
path: captionPath,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: 'blabla',
fields,
attaches,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
// token: server.accessToken,
// fields,
// attaches,
- // statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ // expectedStatus: HttpStatusCode.BAD_REQUEST_400
// })
// })
// videoId: video.uuid,
// fixture: 'subtitle-bad.txt',
// mimeType: 'application/octet-stream',
- // statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ // expectedStatus: HttpStatusCode.BAD_REQUEST_400
// })
// })
it('Should succeed with a valid captionfile extension and octet-stream mime type', async function () {
- await createVideoCaption({
- url: server.url,
- accessToken: server.accessToken,
+ await server.captions.add({
language: 'zh',
videoId: video.uuid,
fixture: 'subtitle-good.srt',
// token: server.accessToken,
// fields,
// attaches,
- // statusCodeExpected: HttpStatusCode.INTERNAL_SERVER_ERROR_500
+ // expectedStatus: HttpStatusCode.INTERNAL_SERVER_ERROR_500
// })
// })
token: server.accessToken,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeGetRequest({
url: server.url,
path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: path + video.shortUUID + '/captions', statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: path + video.shortUUID + '/captions', expectedStatus: HttpStatusCode.OK_200 })
})
})
url: server.url,
path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions/fr',
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should fail without access token', async function () {
const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({ url: server.url, path: captionPath, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeDeleteRequest({ url: server.url, path: captionPath, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a bad access token', async function () {
const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({ url: server.url, path: captionPath, token: 'coucou', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeDeleteRequest({ url: server.url, path: captionPath, token: 'coucou', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with another user', async function () {
url: server.url,
path: captionPath,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
url: server.url,
path: captionPath,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
import 'mocha'
import * as chai from 'chai'
import { omit } from 'lodash'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
buildAbsoluteFixturePath,
+ ChannelsCommand,
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- deleteVideoChannel,
- flushAndRunServer,
- getAccountVideoChannelsList,
- immutableAssign,
+ createSingleServer,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
makeUploadRequest,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { VideoChannelUpdate } from '../../../../shared/models/videos'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoChannelUpdate } from '@shared/models'
const expect = chai.expect
describe('Test video channels API validator', function () {
const videoChannelPath = '/api/v1/video-channels'
- let server: ServerInfo
+ let server: PeerTubeServer
let accessTokenUser: string
+ let command: ChannelsCommand
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
}
{
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- accessTokenUser = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ accessTokenUser = await server.login.getAccessToken(user)
}
+
+ command = server.channels
})
describe('When listing a video channels', function () {
})
it('Should fail with a unknown account', async function () {
- await getAccountVideoChannelsList({ url: server.url, accountName: 'unknown', specialStatus: HttpStatusCode.NOT_FOUND_404 })
+ await server.channels.listByAccount({ accountName: 'unknown', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct parameters', async function () {
await makeGetRequest({
url: server.url,
path: accountChannelPath,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
path: videoChannelPath,
token: 'none',
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
})
it('Should fail with a bad name', async function () {
- const fields = immutableAssign(baseCorrectParams, { name: 'super name' })
+ const fields = { ...baseCorrectParams, name: 'super name' }
await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
})
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { displayName: 'super'.repeat(25) })
+ const fields = { ...baseCorrectParams, displayName: 'super'.repeat(25) }
await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(201) }
await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
})
path: videoChannelPath,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
path: videoChannelPath,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
})
path,
token: 'hi',
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: accessTokenUser,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { displayName: 'super'.repeat(25) })
+ const fields = { ...baseCorrectParams, displayName: 'super'.repeat(25) }
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(201) }
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad bulkVideosSupportUpdate field', async function () {
- const fields = immutableAssign(baseCorrectParams, { bulkVideosSupportUpdate: 'super' })
+ const fields = { ...baseCorrectParams, bulkVideosSupportUpdate: 'super' }
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
path: `${path}/${type}/pick`,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
}
})
token: server.accessToken,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
}
})
const res = await makeGetRequest({
url: server.url,
path: videoChannelPath,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.data).to.be.an('array')
await makeGetRequest({
url: server.url,
path: videoChannelPath + '/super_channel2',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
await makeGetRequest({
url: server.url,
path: videoChannelPath + '/super_channel',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
describe('When deleting a video channel', function () {
it('Should fail with a non authenticated user', async function () {
- await deleteVideoChannel(server.url, 'coucou', 'super_channel', HttpStatusCode.UNAUTHORIZED_401)
+ await command.delete({ token: 'coucou', channelName: 'super_channel', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with another authenticated user', async function () {
- await deleteVideoChannel(server.url, accessTokenUser, 'super_channel', HttpStatusCode.FORBIDDEN_403)
+ await command.delete({ token: accessTokenUser, channelName: 'super_channel', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with an unknown video channel id', async function () {
- await deleteVideoChannel(server.url, server.accessToken, 'super_channel2', HttpStatusCode.NOT_FOUND_404)
+ await command.delete({ channelName: 'super_channel2', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the correct parameters', async function () {
- await deleteVideoChannel(server.url, server.accessToken, 'super_channel')
+ await command.delete({ channelName: 'super_channel' })
})
it('Should fail to delete the last user video channel', async function () {
- await deleteVideoChannel(server.url, server.accessToken, 'root_channel', HttpStatusCode.CONFLICT_409)
+ await command.delete({ channelName: 'root_channel', expectedStatus: HttpStatusCode.CONFLICT_409 })
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoCreateResult } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- flushAndRunServer,
+ createSingleServer,
makeDeleteRequest,
makeGetRequest,
makePostBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoCreateResult } from '@shared/models'
const expect = chai.expect
describe('Test video comments API validator', function () {
let pathThread: string
let pathComment: string
- let server: ServerInfo
+ let server: PeerTubeServer
let video: VideoCreateResult
let userAccessToken: string
let userAccessToken2: string
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
{
- const res = await uploadVideo(server.url, server.accessToken, {})
- video = res.body.video
+ video = await server.videos.upload({ attributes: {} })
pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
}
{
- const res = await addVideoCommentThread(server.url, server.accessToken, video.uuid, 'coucou')
- commentId = res.body.comment.id
+ const created = await server.comments.createThread({ videoId: video.uuid, text: 'coucou' })
+ commentId = created.id
pathComment = '/api/v1/videos/' + video.uuid + '/comments/' + commentId
}
{
const user = { username: 'user1', password: 'my super password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
}
{
const user = { username: 'user2', password: 'my super password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken2 = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken2 = await server.login.getAccessToken(user)
}
})
await makeGetRequest({
url: server.url,
path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
})
await makeGetRequest({
url: server.url,
path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads/' + commentId,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
await makeGetRequest({
url: server.url,
path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/156',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
await makeGetRequest({
url: server.url,
path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/' + commentId,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
path: pathThread,
token: 'none',
fields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: pathThread,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
path: pathComment,
token: 'none',
fields,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: pathComment,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
describe('When removing video comments', function () {
it('Should fail with a non authenticated user', async function () {
- await makeDeleteRequest({ url: server.url, path: pathComment, token: 'none', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeDeleteRequest({ url: server.url, path: pathComment, token: 'none', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with another user', async function () {
url: server.url,
path: pathComment,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should fail with an incorrect video', async function () {
const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comments/' + commentId
- await makeDeleteRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with an incorrect comment', async function () {
const path = '/api/v1/videos/' + video.uuid + '/comments/124'
- await makeDeleteRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
+ await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should succeed with the same user', async function () {
let commentToDelete: number
{
- const res = await addVideoCommentThread(server.url, userAccessToken, video.uuid, 'hello')
- commentToDelete = res.body.comment.id
+ const created = await server.comments.createThread({ videoId: video.uuid, token: userAccessToken, text: 'hello' })
+ commentToDelete = created.id
}
const path = '/api/v1/videos/' + video.uuid + '/comments/' + commentToDelete
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.NO_CONTENT_204 })
+ await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
+ await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
})
it('Should succeed with the owner of the video', async function () {
let anotherVideoUUID: string
{
- const res = await uploadVideo(server.url, userAccessToken, { name: 'video' })
- anotherVideoUUID = res.body.video.uuid
+ const { uuid } = await server.videos.upload({ token: userAccessToken, attributes: { name: 'video' } })
+ anotherVideoUUID = uuid
}
{
- const res = await addVideoCommentThread(server.url, server.accessToken, anotherVideoUUID, 'hello')
- commentToDelete = res.body.comment.id
+ const created = await server.comments.createThread({ videoId: anotherVideoUUID, text: 'hello' })
+ commentToDelete = created.id
}
const path = '/api/v1/videos/' + anotherVideoUUID + '/comments/' + commentToDelete
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.NO_CONTENT_204 })
+ await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
+ await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
})
it('Should succeed with the correct parameters', async function () {
url: server.url,
path: pathComment,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
describe('When a video has comments disabled', function () {
before(async function () {
- const res = await uploadVideo(server.url, server.accessToken, { commentsEnabled: false })
- video = res.body.video
+ video = await server.videos.upload({ attributes: { commentsEnabled: false } })
pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
})
const res = await makeGetRequest({
url: server.url,
path: pathThread,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.total).to.equal(0)
expect(res.body.data).to.have.lengthOf(0)
path: pathThread,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
url: server.url,
path,
token: userAccessToken,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
searchAccount: 'toto',
searchVideo: 'toto'
},
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
import 'mocha'
import { omit } from 'lodash'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
buildAbsoluteFixturePath,
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
cleanupTests,
- createUser,
- flushAndRunServer,
- getMyUserInformation,
- immutableAssign,
+ createSingleServer,
+ FIXTURE_URLS,
makeGetRequest,
makePostBodyRequest,
makeUploadRequest,
- ServerInfo,
- setAccessTokensToServers,
- updateCustomSubConfig,
- userLogin
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { getGoodVideoUrl, getMagnetURI } from '../../../../shared/extra-utils/videos/video-imports'
-import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
describe('Test video imports API validator', function () {
const path = '/api/v1/videos/imports'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
let channelId: number
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
const username = 'user1'
const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
- userAccessToken = await userLogin(server, { username, password })
+ await server.users.create({ username: username, password: password })
+ userAccessToken = await server.login.getAccessToken({ username, password })
{
- const res = await getMyUserInformation(server.url, server.accessToken)
- channelId = res.body.videoChannels[0].id
+ const { videoChannels } = await server.users.getMyInfo()
+ channelId = videoChannels[0].id
}
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: myPath, statusCodeExpected: HttpStatusCode.OK_200, token: server.accessToken })
+ await makeGetRequest({ url: server.url, path: myPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
})
})
before(function () {
baseCorrectParams = {
- targetUrl: getGoodVideoUrl(),
+ targetUrl: FIXTURE_URLS.goodVideo,
name: 'my super name',
category: 5,
licence: 1,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail with a bad target url', async function () {
- const fields = immutableAssign(baseCorrectParams, { targetUrl: 'htt://hello' })
+ const fields = { ...baseCorrectParams, targetUrl: 'htt://hello' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(65) })
+ const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad category', async function () {
- const fields = immutableAssign(baseCorrectParams, { category: 125 })
+ const fields = { ...baseCorrectParams, category: 125 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad licence', async function () {
- const fields = immutableAssign(baseCorrectParams, { licence: 125 })
+ const fields = { ...baseCorrectParams, licence: 125 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a bad language', async function () {
- const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
+ const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
})
it('Should fail with a bad channel', async function () {
- const fields = immutableAssign(baseCorrectParams, { channelId: 545454 })
+ const fields = { ...baseCorrectParams, channelId: 545454 }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
username: 'fake',
password: 'fake_password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- const accessTokenUser = await userLogin(server, user)
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const customChannelId = res.body.videoChannels[0].id
+ const accessTokenUser = await server.login.getAccessToken(user)
+ const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
+ const customChannelId = videoChannels[0].id
- const fields = immutableAssign(baseCorrectParams, { channelId: customChannelId })
+ const fields = { ...baseCorrectParams, channelId: customChannelId }
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
})
it('Should fail with too many tags', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a tag length too low', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 't' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a tag length too big', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with an invalid magnet URI', async function () {
let fields = omit(baseCorrectParams, 'targetUrl')
- fields = immutableAssign(fields, { magnetUri: 'blabla' })
+ fields = { ...fields, magnetUri: 'blabla' }
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
it('Should forbid to import http videos', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- import: {
- videos: {
- http: {
- enabled: false
- },
- torrent: {
- enabled: true
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ import: {
+ videos: {
+ http: {
+ enabled: false
+ },
+ torrent: {
+ enabled: true
+ }
}
}
}
path,
token: server.accessToken,
fields: baseCorrectParams,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
it('Should forbid to import torrent videos', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- import: {
- videos: {
- http: {
- enabled: true
- },
- torrent: {
- enabled: false
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ import: {
+ videos: {
+ http: {
+ enabled: true
+ },
+ torrent: {
+ enabled: false
+ }
}
}
}
})
let fields = omit(baseCorrectParams, 'targetUrl')
- fields = immutableAssign(fields, { magnetUri: getMagnetURI() })
+ fields = { ...fields, magnetUri: FIXTURE_URLS.magnet }
await makePostBodyRequest({
url: server.url,
path,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
fields = omit(fields, 'magnetUri')
token: server.accessToken,
fields,
attaches,
- statusCodeExpected: HttpStatusCode.CONFLICT_409
+ expectedStatus: HttpStatusCode.CONFLICT_409
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { VideoPlaylistCreateResult, VideoPlaylistPrivacy, VideoPlaylistType } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoInPlaylist,
checkBadCountPagination,
checkBadSortPagination,
checkBadStartPagination,
cleanupTests,
- createVideoPlaylist,
- deleteVideoPlaylist,
- flushAndRunServer,
- generateUserAccessToken,
- getAccountPlaylistsListWithToken,
- getVideoPlaylist,
- immutableAssign,
+ createSingleServer,
makeGetRequest,
- removeVideoFromPlaylist,
- reorderVideosPlaylist,
- ServerInfo,
+ PeerTubeServer,
+ PlaylistsCommand,
setAccessTokensToServers,
- setDefaultVideoChannel,
- updateVideoPlaylist,
- updateVideoPlaylistElement,
- uploadVideoAndGetId
-} from '../../../../shared/extra-utils'
+ setDefaultVideoChannel
+} from '@shared/extra-utils'
+import {
+ HttpStatusCode,
+ VideoPlaylistCreate,
+ VideoPlaylistCreateResult,
+ VideoPlaylistElementCreate,
+ VideoPlaylistElementUpdate,
+ VideoPlaylistPrivacy,
+ VideoPlaylistReorder,
+ VideoPlaylistType
+} from '@shared/models'
describe('Test video playlists API validator', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
let playlist: VideoPlaylistCreateResult
let watchLaterPlaylistId: number
let videoId: number
- let playlistElementId: number
+ let elementId: number
+
+ let command: PlaylistsCommand
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
- userAccessToken = await generateUserAccessToken(server, 'user1')
- videoId = (await uploadVideoAndGetId({ server, videoName: 'video 1' })).id
+ userAccessToken = await server.users.generateUserAndToken('user1')
+ videoId = (await server.videos.quickUpload({ name: 'video 1' })).id
+
+ command = server.playlists
{
- const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
- watchLaterPlaylistId = res.body.data[0].id
+ const { data } = await command.listByAccount({
+ token: server.accessToken,
+ handle: 'root',
+ start: 0,
+ count: 5,
+ playlistType: VideoPlaylistType.WATCH_LATER
+ })
+ watchLaterPlaylistId = data[0].id
}
{
- const res = await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ playlist = await command.create({
+ attributes: {
displayName: 'super playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: server.store.channel.id
}
})
- playlist = res.body.videoPlaylist
}
{
- const res = await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ const created = await command.create({
+ attributes: {
displayName: 'private',
privacy: VideoPlaylistPrivacy.PRIVATE
}
})
- privatePlaylistUUID = res.body.videoPlaylist.uuid
+ privatePlaylistUUID = created.uuid
}
})
await makeGetRequest({
url: server.url,
path: accountPath,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404,
+ expectedStatus: HttpStatusCode.NOT_FOUND_404,
token: server.accessToken
})
})
await makeGetRequest({
url: server.url,
path: accountPath,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404,
+ expectedStatus: HttpStatusCode.NOT_FOUND_404,
token: server.accessToken
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: globalPath, statusCodeExpected: HttpStatusCode.OK_200, token: server.accessToken })
- await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: HttpStatusCode.OK_200, token: server.accessToken })
+ await makeGetRequest({ url: server.url, path: globalPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
+ await makeGetRequest({ url: server.url, path: accountPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
await makeGetRequest({
url: server.url,
path: videoChannelPath,
- statusCodeExpected: HttpStatusCode.OK_200,
+ expectedStatus: HttpStatusCode.OK_200,
token: server.accessToken
})
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: path + playlist.shortUUID + '/videos', statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: path + playlist.shortUUID + '/videos', expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('When getting a video playlist', function () {
it('Should fail with a bad id or uuid', async function () {
- await getVideoPlaylist(server.url, 'toto', HttpStatusCode.BAD_REQUEST_400)
+ await command.get({ playlistId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with an unknown playlist', async function () {
- await getVideoPlaylist(server.url, 42, HttpStatusCode.NOT_FOUND_404)
+ await command.get({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail to get an unlisted playlist with the number id', async function () {
- const res = await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ const playlist = await command.create({
+ attributes: {
displayName: 'super playlist',
- videoChannelId: server.videoChannel.id,
+ videoChannelId: server.store.channel.id,
privacy: VideoPlaylistPrivacy.UNLISTED
}
})
- const playlist = res.body.videoPlaylist
- await getVideoPlaylist(server.url, playlist.id, HttpStatusCode.NOT_FOUND_404)
- await getVideoPlaylist(server.url, playlist.uuid, HttpStatusCode.OK_200)
+ await command.get({ playlistId: playlist.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should succeed with the correct params', async function () {
- await getVideoPlaylist(server.url, playlist.uuid, HttpStatusCode.OK_200)
+ await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('When creating/updating a video playlist', function () {
- const getBase = (playlistAttrs: any = {}, wrapper: any = {}) => {
- return Object.assign({
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- url: server.url,
- token: server.accessToken,
- playlistAttrs: Object.assign({
+ const getBase = (
+ attributes?: Partial<VideoPlaylistCreate>,
+ wrapper?: Partial<Parameters<PlaylistsCommand['create']>[0]>
+ ) => {
+ return {
+ attributes: {
displayName: 'display name',
privacy: VideoPlaylistPrivacy.UNLISTED,
thumbnailfile: 'thumbnail.jpg',
- videoChannelId: server.videoChannel.id
- }, playlistAttrs)
- }, wrapper)
+ videoChannelId: server.store.channel.id,
+
+ ...attributes
+ },
+
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+
+ ...wrapper
+ }
}
const getUpdate = (params: any, playlistId: number | string) => {
- return immutableAssign(params, { playlistId: playlistId })
+ return { ...params, playlistId: playlistId }
}
it('Should fail with an unauthenticated user', async function () {
const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail without displayName', async function () {
const params = getBase({ displayName: undefined })
- await createVideoPlaylist(params)
+ await command.create(params)
})
it('Should fail with an incorrect display name', async function () {
const params = getBase({ displayName: 's'.repeat(300) })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail with an incorrect description', async function () {
const params = getBase({ description: 't' })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail with an incorrect privacy', async function () {
const params = getBase({ privacy: 45 })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail with an unknown video channel id', async function () {
const params = getBase({ videoChannelId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail with an incorrect thumbnail file', async function () {
const params = getBase({ thumbnailfile: 'video_short.mp4' })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail with a thumbnail file too big', async function () {
const params = getBase({ thumbnailfile: 'preview-big.png' })
- await createVideoPlaylist(params)
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.create(params)
+ await command.update(getUpdate(params, playlist.shortUUID))
})
it('Should fail to set "public" a playlist not assigned to a channel', async function () {
const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined })
- const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' })
- const params3 = getBase({ privacy: undefined, videoChannelId: 'null' })
+ const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' as any })
+ const params3 = getBase({ privacy: undefined, videoChannelId: 'null' as any })
- await createVideoPlaylist(params)
- await createVideoPlaylist(params2)
- await updateVideoPlaylist(getUpdate(params, privatePlaylistUUID))
- await updateVideoPlaylist(getUpdate(params2, playlist.shortUUID))
- await updateVideoPlaylist(getUpdate(params3, playlist.shortUUID))
+ await command.create(params)
+ await command.create(params2)
+ await command.update(getUpdate(params, privatePlaylistUUID))
+ await command.update(getUpdate(params2, playlist.shortUUID))
+ await command.update(getUpdate(params3, playlist.shortUUID))
})
it('Should fail with an unknown playlist to update', async function () {
- await updateVideoPlaylist(getUpdate(
+ await command.update(getUpdate(
getBase({}, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }),
42
))
})
it('Should fail to update a playlist of another user', async function () {
- await updateVideoPlaylist(getUpdate(
+ await command.update(getUpdate(
getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }),
playlist.shortUUID
))
})
it('Should fail to update the watch later playlist', async function () {
- await updateVideoPlaylist(getUpdate(
+ await command.update(getUpdate(
getBase({}, { expectedStatus: HttpStatusCode.BAD_REQUEST_400 }),
watchLaterPlaylistId
))
it('Should succeed with the correct params', async function () {
{
const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
- await createVideoPlaylist(params)
+ await command.create(params)
}
{
const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await updateVideoPlaylist(getUpdate(params, playlist.shortUUID))
+ await command.update(getUpdate(params, playlist.shortUUID))
}
})
})
describe('When adding an element in a playlist', function () {
- const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
- return Object.assign({
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- url: server.url,
- token: server.accessToken,
- playlistId: playlist.id,
- elementAttrs: Object.assign({
+ const getBase = (
+ attributes?: Partial<VideoPlaylistElementCreate>,
+ wrapper?: Partial<Parameters<PlaylistsCommand['addElement']>[0]>
+ ) => {
+ return {
+ attributes: {
videoId,
startTimestamp: 2,
- stopTimestamp: 3
- }, elementAttrs)
- }, wrapper)
+ stopTimestamp: 3,
+
+ ...attributes
+ },
+
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+ playlistId: playlist.id,
+
+ ...wrapper
+ }
}
it('Should fail with an unauthenticated user', async function () {
const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
})
it('Should fail with the playlist of another user', async function () {
const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
})
it('Should fail with an unknown or incorrect playlist id', async function () {
{
const params = getBase({}, { playlistId: 'toto' })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
}
{
const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
}
})
it('Should fail with an unknown or incorrect video id', async function () {
const params = getBase({ videoId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
})
it('Should fail with a bad start/stop timestamp', async function () {
{
const params = getBase({ startTimestamp: -42 })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
}
{
const params = getBase({ stopTimestamp: 'toto' as any })
- await addVideoInPlaylist(params)
+ await command.addElement(params)
}
})
it('Succeed with the correct params', async function () {
const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
- const res = await addVideoInPlaylist(params)
- playlistElementId = res.body.videoPlaylistElement.id
+ const created = await command.addElement(params)
+ elementId = created.id
})
})
describe('When updating an element in a playlist', function () {
- const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
- return Object.assign({
- url: server.url,
- token: server.accessToken,
- elementAttrs: Object.assign({
+ const getBase = (
+ attributes?: Partial<VideoPlaylistElementUpdate>,
+ wrapper?: Partial<Parameters<PlaylistsCommand['updateElement']>[0]>
+ ) => {
+ return {
+ attributes: {
startTimestamp: 1,
- stopTimestamp: 2
- }, elementAttrs),
- playlistElementId,
+ stopTimestamp: 2,
+
+ ...attributes
+ },
+
+ elementId,
playlistId: playlist.id,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- }, wrapper)
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+
+ ...wrapper
+ }
}
it('Should fail with an unauthenticated user', async function () {
const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
})
it('Should fail with the playlist of another user', async function () {
const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
})
it('Should fail with an unknown or incorrect playlist id', async function () {
{
const params = getBase({}, { playlistId: 'toto' })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
}
{
const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
}
})
it('Should fail with an unknown or incorrect playlistElement id', async function () {
{
- const params = getBase({}, { playlistElementId: 'toto' })
- await updateVideoPlaylistElement(params)
+ const params = getBase({}, { elementId: 'toto' })
+ await command.updateElement(params)
}
{
- const params = getBase({}, { playlistElementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await updateVideoPlaylistElement(params)
+ const params = getBase({}, { elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await command.updateElement(params)
}
})
it('Should fail with a bad start/stop timestamp', async function () {
{
const params = getBase({ startTimestamp: 'toto' as any })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
}
{
const params = getBase({ stopTimestamp: -42 })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
}
})
it('Should fail with an unknown element', async function () {
- const params = getBase({}, { playlistElementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await updateVideoPlaylistElement(params)
+ const params = getBase({}, { elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await command.updateElement(params)
})
it('Succeed with the correct params', async function () {
const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await updateVideoPlaylistElement(params)
+ await command.updateElement(params)
})
})
let videoId3: number
let videoId4: number
- const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
- return Object.assign({
- url: server.url,
- token: server.accessToken,
- playlistId: playlist.shortUUID,
- elementAttrs: Object.assign({
+ const getBase = (
+ attributes?: Partial<VideoPlaylistReorder>,
+ wrapper?: Partial<Parameters<PlaylistsCommand['reorderElements']>[0]>
+ ) => {
+ return {
+ attributes: {
startPosition: 1,
insertAfterPosition: 2,
- reorderLength: 3
- }, elementAttrs),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- }, wrapper)
+ reorderLength: 3,
+
+ ...attributes
+ },
+
+ playlistId: playlist.shortUUID,
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+
+ ...wrapper
+ }
}
before(async function () {
- videoId3 = (await uploadVideoAndGetId({ server, videoName: 'video 3' })).id
- videoId4 = (await uploadVideoAndGetId({ server, videoName: 'video 4' })).id
+ videoId3 = (await server.videos.quickUpload({ name: 'video 3' })).id
+ videoId4 = (await server.videos.quickUpload({ name: 'video 4' })).id
for (const id of [ videoId3, videoId4 ]) {
- await addVideoInPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: playlist.shortUUID,
- elementAttrs: { videoId: id }
- })
+ await command.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: id } })
}
})
it('Should fail with an unauthenticated user', async function () {
const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
})
it('Should fail with the playlist of another user', async function () {
const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
})
it('Should fail with an invalid playlist', async function () {
{
const params = getBase({}, { playlistId: 'toto' })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
})
it('Should fail with an invalid start position', async function () {
{
const params = getBase({ startPosition: -1 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ startPosition: 'toto' as any })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ startPosition: 42 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
})
it('Should fail with an invalid insert after position', async function () {
{
const params = getBase({ insertAfterPosition: 'toto' as any })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ insertAfterPosition: -2 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ insertAfterPosition: 42 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
})
it('Should fail with an invalid reorder length', async function () {
{
const params = getBase({ reorderLength: 'toto' as any })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ reorderLength: -2 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
{
const params = getBase({ reorderLength: 42 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
}
})
it('Succeed with the correct params', async function () {
const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await reorderVideosPlaylist(params)
+ await command.reorderElements(params)
})
})
url: server.url,
path,
query: { videoIds: [ 1, 2 ] },
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
token: server.accessToken,
path,
query: { videoIds: [ 1, 2 ] },
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
})
describe('When deleting an element in a playlist', function () {
- const getBase = (wrapper: any = {}) => {
- return Object.assign({
- url: server.url,
- token: server.accessToken,
- playlistElementId,
+ const getBase = (wrapper: Partial<Parameters<PlaylistsCommand['removeElement']>[0]>) => {
+ return {
+ elementId,
playlistId: playlist.uuid,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- }, wrapper)
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+
+ ...wrapper
+ }
}
it('Should fail with an unauthenticated user', async function () {
const params = getBase({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await removeVideoFromPlaylist(params)
+ await command.removeElement(params)
})
it('Should fail with the playlist of another user', async function () {
const params = getBase({ token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await removeVideoFromPlaylist(params)
+ await command.removeElement(params)
})
it('Should fail with an unknown or incorrect playlist id', async function () {
{
const params = getBase({ playlistId: 'toto' })
- await removeVideoFromPlaylist(params)
+ await command.removeElement(params)
}
{
const params = getBase({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await removeVideoFromPlaylist(params)
+ await command.removeElement(params)
}
})
it('Should fail with an unknown or incorrect video id', async function () {
{
- const params = getBase({ playlistElementId: 'toto' })
- await removeVideoFromPlaylist(params)
+ const params = getBase({ elementId: 'toto' as any })
+ await command.removeElement(params)
}
{
- const params = getBase({ playlistElementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await removeVideoFromPlaylist(params)
+ const params = getBase({ elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await command.removeElement(params)
}
})
it('Should fail with an unknown element', async function () {
- const params = getBase({ playlistElementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await removeVideoFromPlaylist(params)
+ const params = getBase({ elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await command.removeElement(params)
})
it('Succeed with the correct params', async function () {
const params = getBase({ expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await removeVideoFromPlaylist(params)
+ await command.removeElement(params)
})
})
describe('When deleting a playlist', function () {
it('Should fail with an unknown playlist', async function () {
- await deleteVideoPlaylist(server.url, server.accessToken, 42, HttpStatusCode.NOT_FOUND_404)
+ await command.delete({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a playlist of another user', async function () {
- await deleteVideoPlaylist(server.url, userAccessToken, playlist.uuid, HttpStatusCode.FORBIDDEN_403)
+ await command.delete({ token: userAccessToken, playlistId: playlist.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with the watch later playlist', async function () {
- await deleteVideoPlaylist(server.url, server.accessToken, watchLaterPlaylistId, HttpStatusCode.BAD_REQUEST_400)
+ await command.delete({ playlistId: watchLaterPlaylistId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should succeed with the correct params', async function () {
- await deleteVideoPlaylist(server.url, server.accessToken, playlist.uuid)
+ await command.delete({ playlistId: playlist.uuid })
})
})
import 'mocha'
import {
cleanupTests,
- createUser,
- flushAndRunServer,
+ createSingleServer,
makeGetRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- setDefaultVideoChannel,
- userLogin
-} from '../../../../shared/extra-utils'
-import { UserRole } from '../../../../shared/models/users'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ setDefaultVideoChannel
+} from '@shared/extra-utils'
+import { HttpStatusCode, UserRole } from '@shared/models'
-async function testEndpoints (server: ServerInfo, token: string, filter: string, statusCodeExpected: HttpStatusCode) {
+async function testEndpoints (server: PeerTubeServer, token: string, filter: string, expectedStatus: HttpStatusCode) {
const paths = [
'/api/v1/video-channels/root_channel/videos',
'/api/v1/accounts/root/videos',
query: {
filter
},
- statusCodeExpected
+ expectedStatus
})
}
}
describe('Test video filters validators', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
let moderatorAccessToken: string
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
const user = { username: 'user1', password: 'my super password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
const moderator = { username: 'moderator', password: 'my super password' }
- await createUser(
- {
- url: server.url,
- accessToken: server.accessToken,
- username: moderator.username,
- password: moderator.password,
- videoQuota: undefined,
- videoQuotaDaily: undefined,
- role: UserRole.MODERATOR
- }
- )
- moderatorAccessToken = await userLogin(server, moderator)
+ await server.users.create({ username: moderator.username, password: moderator.password, role: UserRole.MODERATOR })
+
+ moderatorAccessToken = await server.login.getAccessToken(moderator)
})
describe('When setting a video filter', function () {
await makeGetRequest({
url: server.url,
path: '/feeds/videos.json',
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401,
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401,
query: {
filter
}
await makeGetRequest({
url: server.url,
path: '/feeds/videos.json',
- statusCodeExpected: HttpStatusCode.OK_200,
+ expectedStatus: HttpStatusCode.OK_200,
query: {
filter: 'local'
}
checkBadCountPagination,
checkBadStartPagination,
cleanupTests,
- flushAndRunServer,
+ createSingleServer,
makeGetRequest,
makePostBodyRequest,
makePutBodyRequest,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '../../../../shared/extra-utils'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test videos history API validator', function () {
const myHistoryPath = '/api/v1/users/me/history/videos'
const myHistoryRemove = myHistoryPath + '/remove'
let watchingPath: string
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- const res = await uploadVideo(server.url, server.accessToken, {})
- const videoUUID = res.body.video.uuid
-
- watchingPath = '/api/v1/videos/' + videoUUID + '/watching'
+ const { uuid } = await server.videos.upload()
+ watchingPath = '/api/v1/videos/' + uuid + '/watching'
})
describe('When notifying a user is watching a video', function () {
it('Should fail with an unauthenticated user', async function () {
const fields = { currentTime: 5 }
- await makePutBodyRequest({ url: server.url, path: watchingPath, fields, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePutBodyRequest({ url: server.url, path: watchingPath, fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with an incorrect video id', async function () {
path,
fields,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path,
fields,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: watchingPath,
fields,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
path: watchingPath,
fields,
token: server.accessToken,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
})
it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path: myHistoryPath, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makeGetRequest({ url: server.url, path: myHistoryPath, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, token: server.accessToken, path: myHistoryPath, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, token: server.accessToken, path: myHistoryPath, expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('When removing user videos history', function () {
it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
+ await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a bad beforeDate parameter', async function () {
token: server.accessToken,
path: myHistoryRemove,
fields: body,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
token: server.accessToken,
path: myHistoryRemove,
fields: body,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
url: server.url,
token: server.accessToken,
path: myHistoryRemove,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../../shared/extra-utils'
-import { getVideosOverview } from '@shared/extra-utils/overviews/overviews'
+import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/extra-utils'
describe('Test videos overview', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
// ---------------------------------------------------------------
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
})
describe('When getting videos overview', function () {
it('Should fail with a bad pagination', async function () {
- await getVideosOverview(server.url, 0, 400)
- await getVideosOverview(server.url, 100, 400)
+ await server.overviews.getVideos({ page: 0, expectedStatus: 400 })
+ await server.overviews.getVideos({ page: 100, expectedStatus: 400 })
})
it('Should succeed with a good pagination', async function () {
- await getVideosOverview(server.url, 1)
+ await server.overviews.getVideos({ page: 1 })
})
})
import { omit } from 'lodash'
import { join } from 'path'
import { randomInt } from '@shared/core-utils'
-import { PeerTubeProblemDocument, VideoCreateResult } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
+ checkBadCountPagination,
+ checkBadSortPagination,
+ checkBadStartPagination,
checkUploadVideoParam,
cleanupTests,
- createUser,
- flushAndRunServer,
- getMyUserInformation,
- getVideo,
- getVideosList,
- immutableAssign,
+ createSingleServer,
makeDeleteRequest,
makeGetRequest,
makePutBodyRequest,
makeUploadRequest,
- removeVideo,
+ PeerTubeServer,
root,
- ServerInfo,
- setAccessTokensToServers,
- userLogin
-} from '../../../../shared/extra-utils'
-import {
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination
-} from '../../../../shared/extra-utils/requests/check-api-params'
-import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, PeerTubeProblemDocument, VideoCreateResult, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test videos API validator', function () {
const path = '/api/v1/videos/'
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken = ''
let accountName: string
let channelId: number
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
const username = 'user1'
const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
- userAccessToken = await userLogin(server, { username, password })
+ await server.users.create({ username: username, password: password })
+ userAccessToken = await server.login.getAccessToken({ username, password })
{
- const res = await getMyUserInformation(server.url, server.accessToken)
- channelId = res.body.videoChannels[0].id
- channelName = res.body.videoChannels[0].name
- accountName = res.body.account.name + '@' + res.body.account.host
+ const body = await server.users.getMyInfo()
+ channelId = body.videoChannels[0].id
+ channelName = body.videoChannels[0].name
+ accountName = body.account.name + '@' + body.account.host
}
})
})
it('Should fail with a bad skipVideos query', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.OK_200, query: { skipCount: 'toto' } })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200, query: { skipCount: 'toto' } })
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.OK_200, query: { skipCount: false } })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200, query: { skipCount: false } })
})
})
await makeGetRequest({
url: server.url,
path: join(path, 'search'),
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
})
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, token: server.accessToken, path, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, token: server.accessToken, path, expectedStatus: HttpStatusCode.OK_200 })
})
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
})
})
})
it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
})
})
it('Should fail with nothing', async function () {
const fields = {}
const attaches = {}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail without name', async function () {
const fields = omit(baseCorrectParams, 'name')
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(65) })
+ const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad category', async function () {
- const fields = immutableAssign(baseCorrectParams, { category: 125 })
+ const fields = { ...baseCorrectParams, category: 125 }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad licence', async function () {
- const fields = immutableAssign(baseCorrectParams, { licence: 125 })
+ const fields = { ...baseCorrectParams, licence: 125 }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad language', async function () {
- const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
+ const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail without a channel', async function () {
const fields = omit(baseCorrectParams, 'channelId')
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad channel', async function () {
- const fields = immutableAssign(baseCorrectParams, { channelId: 545454 })
+ const fields = { ...baseCorrectParams, channelId: 545454 }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with another user channel', async function () {
username: 'fake' + randomInt(0, 1500),
password: 'fake_password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- const accessTokenUser = await userLogin(server, user)
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const customChannelId = res.body.videoChannels[0].id
+ const accessTokenUser = await server.login.getAccessToken(user)
+ const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
+ const customChannelId = videoChannels[0].id
- const fields = immutableAssign(baseCorrectParams, { channelId: customChannelId })
+ const fields = { ...baseCorrectParams, channelId: customChannelId }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, userAccessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, userAccessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with too many tags', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a tag length too low', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 't' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a tag length too big', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad schedule update (miss updateAt)', async function () {
- const fields = immutableAssign(baseCorrectParams, { scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } })
+ const fields = { ...baseCorrectParams, scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad schedule update (wrong updateAt)', async function () {
- const fields = immutableAssign(baseCorrectParams, {
+ const fields = {
+ ...baseCorrectParams,
+
scheduleUpdate: {
privacy: VideoPrivacy.PUBLIC,
updateAt: 'toto'
}
- })
+ }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a bad originally published at attribute', async function () {
- const fields = immutableAssign(baseCorrectParams, { originallyPublishedAt: 'toto' })
+ const fields = { ...baseCorrectParams, originallyPublishedAt: 'toto' }
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail without an input file', async function () {
const fields = baseCorrectParams
const attaches = {}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with an incorrect input file', async function () {
let attaches = { fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm') }
await checkUploadVideoParam(
- server.url,
+ server,
server.accessToken,
{ ...fields, ...attaches },
HttpStatusCode.UNPROCESSABLE_ENTITY_422,
attaches = { fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv') }
await checkUploadVideoParam(
- server.url,
+ server,
server.accessToken,
{ ...fields, ...attaches },
HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415,
fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a big thumbnail file', async function () {
fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with an incorrect preview file', async function () {
fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should fail with a big preview file', async function () {
fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
}
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.BAD_REQUEST_400, mode)
})
it('Should report the appropriate error', async function () {
- const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
+ const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
const attaches = baseCorrectAttaches
const attributes = { ...fields, ...attaches }
- const res = await checkUploadVideoParam(server.url, server.accessToken, attributes, HttpStatusCode.BAD_REQUEST_400, mode)
+ const body = await checkUploadVideoParam(server, server.accessToken, attributes, HttpStatusCode.BAD_REQUEST_400, mode)
- const error = res.body as PeerTubeProblemDocument
+ const error = body as unknown as PeerTubeProblemDocument
if (mode === 'legacy') {
expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy')
{
const attaches = baseCorrectAttaches
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
}
{
- const attaches = immutableAssign(baseCorrectAttaches, {
+ const attaches = {
+ ...baseCorrectAttaches,
+
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- })
+ }
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
}
{
- const attaches = immutableAssign(baseCorrectAttaches, {
+ const attaches = {
+ ...baseCorrectAttaches,
+
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.ogv')
- })
+ }
- await checkUploadVideoParam(server.url, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
+ await checkUploadVideoParam(server, server.accessToken, { ...fields, ...attaches }, HttpStatusCode.OK_200, mode)
}
})
}
}
before(async function () {
- const res = await getVideosList(server.url)
- video = res.body.data[0]
+ const { data } = await server.videos.list()
+ video = data[0]
})
it('Should fail with nothing', async function () {
path: path + '4da6fde3-88f7-4d16-b119-108df5630b06',
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should fail with a long name', async function () {
- const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(65) })
+ const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad category', async function () {
- const fields = immutableAssign(baseCorrectParams, { category: 125 })
+ const fields = { ...baseCorrectParams, category: 125 }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad licence', async function () {
- const fields = immutableAssign(baseCorrectParams, { licence: 125 })
+ const fields = { ...baseCorrectParams, licence: 125 }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad language', async function () {
- const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
+ const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
- const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) })
+ const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
- const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
+ const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad channel', async function () {
- const fields = immutableAssign(baseCorrectParams, { channelId: 545454 })
+ const fields = { ...baseCorrectParams, channelId: 545454 }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with too many tags', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a tag length too low', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 't' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a tag length too big', async function () {
- const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] })
+ const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad schedule update (miss updateAt)', async function () {
- const fields = immutableAssign(baseCorrectParams, { scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } })
+ const fields = { ...baseCorrectParams, scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad schedule update (wrong updateAt)', async function () {
- const fields = immutableAssign(baseCorrectParams, { scheduleUpdate: { updateAt: 'toto', privacy: VideoPrivacy.PUBLIC } })
+ const fields = { ...baseCorrectParams, scheduleUpdate: { updateAt: 'toto', privacy: VideoPrivacy.PUBLIC } }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
it('Should fail with a bad originally published at param', async function () {
- const fields = immutableAssign(baseCorrectParams, { originallyPublishedAt: 'toto' })
+ const fields = { ...baseCorrectParams, originallyPublishedAt: 'toto' }
await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
})
path: path + video.shortUUID,
token: userAccessToken,
fields,
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should fail with a video of another server')
it('Shoud report the appropriate error', async function () {
- const fields = immutableAssign(baseCorrectParams, { licence: 125 })
+ const fields = { ...baseCorrectParams, licence: 125 }
const res = await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
const error = res.body as PeerTubeProblemDocument
path: path + video.shortUUID,
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
const res = await makeGetRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.data).to.be.an('array')
})
it('Should fail without a correct uuid', async function () {
- await getVideo(server.url, 'coucou', HttpStatusCode.BAD_REQUEST_400)
+ await server.videos.get({ id: 'coucou', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should return 404 with an incorrect video', async function () {
- await getVideo(server.url, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404)
+ await server.videos.get({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Shoud report the appropriate error', async function () {
- const res = await getVideo(server.url, 'hi', HttpStatusCode.BAD_REQUEST_400)
- const error = res.body as PeerTubeProblemDocument
+ const body = await server.videos.get({ id: 'hi', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ const error = body as unknown as PeerTubeProblemDocument
expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo')
})
it('Should succeed with the correct parameters', async function () {
- await getVideo(server.url, video.shortUUID)
+ await server.videos.get({ id: video.shortUUID })
})
})
describe('When rating a video', function () {
- let videoId
+ let videoId: number
before(async function () {
- const res = await getVideosList(server.url)
- videoId = res.body.data[0].id
+ const { data } = await server.videos.list()
+ videoId = data[0].id
})
it('Should fail without a valid uuid', async function () {
path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/rate',
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
path: path + videoId + '/rate',
token: server.accessToken,
fields,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
})
await makeDeleteRequest({
url: server.url,
path,
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should fail without a correct uuid', async function () {
- await removeVideo(server.url, server.accessToken, 'hello', HttpStatusCode.BAD_REQUEST_400)
+ await server.videos.remove({ id: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should fail with a video which does not exist', async function () {
- await removeVideo(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404)
+ await server.videos.remove({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should fail with a video of another user without the appropriate right', async function () {
- await removeVideo(server.url, userAccessToken, video.uuid, HttpStatusCode.FORBIDDEN_403)
+ await server.videos.remove({ token: userAccessToken, id: video.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a video of another server')
it('Shoud report the appropriate error', async function () {
- const res = await removeVideo(server.url, server.accessToken, 'hello', HttpStatusCode.BAD_REQUEST_400)
- const error = res.body as PeerTubeProblemDocument
+ const body = await server.videos.remove({ id: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ const error = body as PeerTubeProblemDocument
expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo')
})
it('Should succeed with the correct parameters', async function () {
- await removeVideo(server.url, server.accessToken, video.uuid)
+ await server.videos.remove({ id: video.uuid })
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoDetails, VideoPrivacy } from '@shared/models'
+import { VideoPrivacy } from '@shared/models'
import {
- checkLiveCleanup,
+ checkLiveCleanupAfterSave,
cleanupTests,
- createLive,
+ ConfigCommand,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- generateUser,
- getCustomConfigResolutions,
- getVideo,
- runAndTestFfmpegStreamError,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateCustomSubConfig,
- updateUser,
wait,
- waitJobs,
- waitUntilLivePublished
+ waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
describe('Test live constraints', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let userId: number
let userAccessToken: string
let userChannelId: number
saveReplay
}
- const res = await createLive(servers[0].url, userAccessToken, liveAttributes)
- return res.body.video.uuid as string
+ const { uuid } = await servers[0].live.create({ token: userAccessToken, fields: liveAttributes })
+ return uuid
}
async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
for (const server of servers) {
- const res = await getVideo(server.url, videoId)
-
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: videoId })
expect(video.isLive).to.be.false
expect(video.duration).to.be.greaterThan(0)
}
- await checkLiveCleanup(servers[0], videoId, resolutions)
+ await checkLiveCleanupAfterSave(servers[0], videoId, resolutions)
}
async function waitUntilLivePublishedOnAllServers (videoId: string) {
for (const server of servers) {
- await waitUntilLivePublished(server.url, server.accessToken, videoId)
+ await server.live.waitUntilPublished({ videoId })
}
}
function updateQuota (options: { total: number, daily: number }) {
- return updateUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ return servers[0].users.update({
userId,
videoQuota: options.total,
videoQuotaDaily: options.daily
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true,
+ transcoding: {
+ enabled: false
+ }
}
}
})
{
- const res = await generateUser(servers[0], 'user1')
+ const res = await servers[0].users.generate('user1')
userId = res.userId
userChannelId = res.userChannelId
userAccessToken = res.token
this.timeout(60000)
const userVideoLiveoId = await createLiveWrapper(false)
- await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false)
+ await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
})
it('Should have size limit depending on user global quota if save replay is enabled', async function () {
await wait(5000)
const userVideoLiveoId = await createLiveWrapper(true)
- await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
+ await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
await waitJobs(servers)
await updateQuota({ total: -1, daily: 1 })
const userVideoLiveoId = await createLiveWrapper(true)
- await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
+ await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
await waitJobs(servers)
await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
const userVideoLiveoId = await createLiveWrapper(true)
- await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false)
+ await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
})
it('Should have max duration limit', async function () {
this.timeout(60000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: 1,
- transcoding: {
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
enabled: true,
- resolutions: getCustomConfigResolutions(true)
+ allowReplay: true,
+ maxDuration: 1,
+ transcoding: {
+ enabled: true,
+ resolutions: ConfigCommand.getCustomConfigResolutions(true)
+ }
}
}
})
const userVideoLiveoId = await createLiveWrapper(true)
- await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
+ await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
-import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared/models'
+import { LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
import {
cleanupTests,
- createLive,
+ ConfigCommand,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getCustomConfigResolutions,
- getLive,
- getPlaylistsCount,
- getVideo,
- sendRTMPStreamInVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
- updateCustomSubConfig,
- updateLive,
wait,
- waitJobs,
- waitUntilLivePublished,
- waitUntilLiveWaiting
+ waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
describe('Permanent live', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID: string
async function createLiveWrapper (permanentLive: boolean) {
const attributes: LiveVideoCreate = {
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC,
name: 'my super live',
saveReplay: false,
permanentLive
}
- const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
- return res.body.video.uuid
+ const { uuid } = await servers[0].live.create({ fields: attributes })
+ return uuid
}
async function checkVideoState (videoId: string, state: VideoState) {
for (const server of servers) {
- const res = await getVideo(server.url, videoId)
- expect((res.body as VideoDetails).state.id).to.equal(state)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.state.id).to.equal(state)
}
}
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
enabled: true,
- resolutions: getCustomConfigResolutions(true)
+ allowReplay: true,
+ maxDuration: -1,
+ transcoding: {
+ enabled: true,
+ resolutions: ConfigCommand.getCustomConfigResolutions(true)
+ }
}
}
})
const videoUUID = await createLiveWrapper(false)
{
- const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
- expect(res.body.permanentLive).to.be.false
+ const live = await servers[0].live.get({ videoId: videoUUID })
+ expect(live.permanentLive).to.be.false
}
- await updateLive(servers[0].url, servers[0].accessToken, videoUUID, { permanentLive: true })
+ await servers[0].live.update({ videoId: videoUUID, fields: { permanentLive: true } })
{
- const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
- expect(res.body.permanentLive).to.be.true
+ const live = await servers[0].live.get({ videoId: videoUUID })
+ expect(live.permanentLive).to.be.true
}
})
videoUUID = await createLiveWrapper(true)
- const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
- expect(res.body.permanentLive).to.be.true
+ const live = await servers[0].live.get({ videoId: videoUUID })
+ expect(live.permanentLive).to.be.true
await waitJobs(servers)
})
it('Should stream into this permanent live', async function () {
this.timeout(120000)
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID)
+ const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
for (const server of servers) {
- await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
+ await server.live.waitUntilPublished({ videoId: videoUUID })
}
await checkVideoState(videoUUID, VideoState.PUBLISHED)
- await stopFfmpeg(command)
- await waitUntilLiveWaiting(servers[0].url, servers[0].accessToken, videoUUID)
+ await stopFfmpeg(ffmpegCommand)
+ await servers[0].live.waitUntilWaiting({ videoId: videoUUID })
await waitJobs(servers)
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
-
- const videoDetails = res.body as VideoDetails
+ const videoDetails = await server.videos.get({ id: videoUUID })
expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
}
})
it('Should be able to stream again in the permanent live', async function () {
this.timeout(20000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
enabled: true,
- resolutions: getCustomConfigResolutions(false)
+ allowReplay: true,
+ maxDuration: -1,
+ transcoding: {
+ enabled: true,
+ resolutions: ConfigCommand.getCustomConfigResolutions(false)
+ }
}
}
})
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID)
+ const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
for (const server of servers) {
- await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
+ await server.live.waitUntilPublished({ videoId: videoUUID })
}
await checkVideoState(videoUUID, VideoState.PUBLISHED)
- const count = await getPlaylistsCount(servers[0], videoUUID)
+ const count = await servers[0].live.countPlaylists({ videoUUID })
// master playlist and 720p playlist
expect(count).to.equal(2)
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
import { FfmpegCommand } from 'fluent-ffmpeg'
-import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoToBlacklist,
- checkLiveCleanup,
+ checkLiveCleanupAfterSave,
cleanupTests,
- createLive,
+ ConfigCommand,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getCustomConfigResolutions,
- getVideo,
- getVideosList,
- removeVideo,
- sendRTMPStreamInVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
testFfmpegStreamError,
- updateCustomSubConfig,
- updateVideo,
wait,
- waitJobs,
- waitUntilLiveEnded,
- waitUntilLivePublished,
- waitUntilLiveSaved
-} from '../../../../shared/extra-utils'
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
const expect = chai.expect
describe('Save replay setting', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let liveVideoUUID: string
let ffmpegCommand: FfmpegCommand
async function createLiveWrapper (saveReplay: boolean) {
if (liveVideoUUID) {
try {
- await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ await servers[0].videos.remove({ id: liveVideoUUID })
await waitJobs(servers)
} catch {}
}
const attributes: LiveVideoCreate = {
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC,
name: 'my super live',
saveReplay
}
- const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
- return res.body.video.uuid
+ const { uuid } = await servers[0].live.create({ fields: attributes })
+ return uuid
}
- async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) {
+ async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
for (const server of servers) {
const length = existsInList ? 1 : 0
- const resVideos = await getVideosList(server.url)
- expect(resVideos.body.data).to.have.lengthOf(length)
- expect(resVideos.body.total).to.equal(length)
+ const { data, total } = await server.videos.list()
+ expect(data).to.have.lengthOf(length)
+ expect(total).to.equal(length)
- if (getStatus) {
- await getVideo(server.url, videoId, getStatus)
+ if (expectedStatus) {
+ await server.videos.get({ id: videoId, expectedStatus })
}
}
}
async function checkVideoState (videoId: string, state: VideoState) {
for (const server of servers) {
- const res = await getVideo(server.url, videoId)
- expect((res.body as VideoDetails).state.id).to.equal(state)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.state.id).to.equal(state)
}
}
async function waitUntilLivePublishedOnAllServers (videoId: string) {
for (const server of servers) {
- await waitUntilLivePublished(server.url, server.accessToken, videoId)
+ await server.live.waitUntilPublished({ videoId })
}
}
async function waitUntilLiveSavedOnAllServers (videoId: string) {
for (const server of servers) {
- await waitUntilLiveSaved(server.url, server.accessToken, videoId)
+ await server.live.waitUntilSaved({ videoId })
}
}
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
- enabled: false,
- resolutions: getCustomConfigResolutions(true)
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true,
+ maxDuration: -1,
+ transcoding: {
+ enabled: false,
+ resolutions: ConfigCommand.getCustomConfigResolutions(true)
+ }
}
}
})
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
this.timeout(30000)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await stopFfmpeg(ffmpegCommand)
for (const server of servers) {
- await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
+ await server.live.waitUntilEnded({ videoId: liveVideoUUID })
}
await waitJobs(servers)
await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
// No resolutions saved since we did not save replay
- await checkLiveCleanup(servers[0], liveVideoUUID, [])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
})
it('Should correctly terminate the stream on blacklist and delete the live', async function () {
liveVideoUUID = await createLiveWrapper(false)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
await Promise.all([
- addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
+ servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
testFfmpegStreamError(ffmpegCommand, true)
])
await checkVideosExist(liveVideoUUID, false)
- await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
- await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
+ await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
await wait(5000)
await waitJobs(servers)
- await checkLiveCleanup(servers[0], liveVideoUUID, [])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
})
it('Should correctly terminate the stream on delete and delete the video', async function () {
liveVideoUUID = await createLiveWrapper(false)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await Promise.all([
testFfmpegStreamError(ffmpegCommand, true),
- removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ servers[0].videos.remove({ id: liveVideoUUID })
])
await wait(5000)
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
- await checkLiveCleanup(servers[0], liveVideoUUID, [])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
})
})
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
this.timeout(20000)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await waitJobs(servers)
it('Should update the saved live and correctly federate the updated attributes', async function () {
this.timeout(30000)
- await updateVideo(servers[0].url, servers[0].accessToken, liveVideoUUID, { name: 'video updated' })
+ await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, liveVideoUUID)
- expect(res.body.name).to.equal('video updated')
- expect(res.body.isLive).to.be.false
+ const video = await server.videos.get({ id: liveVideoUUID })
+ expect(video.name).to.equal('video updated')
+ expect(video.isLive).to.be.false
}
})
it('Should have cleaned up the live files', async function () {
- await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
})
it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
liveVideoUUID = await createLiveWrapper(true)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
await Promise.all([
- addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
+ servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
testFfmpegStreamError(ffmpegCommand, true)
])
await checkVideosExist(liveVideoUUID, false)
- await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
- await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
+ await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
await wait(5000)
await waitJobs(servers)
- await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
})
it('Should correctly terminate the stream on delete and delete the video', async function () {
liveVideoUUID = await createLiveWrapper(true)
- ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
await Promise.all([
- removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
+ servers[0].videos.remove({ id: liveVideoUUID }),
testFfmpegStreamError(ffmpegCommand, true)
])
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
- await checkLiveCleanup(servers[0], liveVideoUUID, [])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
})
})
import 'mocha'
import * as chai from 'chai'
-import { getLiveNotificationSocket } from '@shared/extra-utils/socket/socket-io'
import { VideoPrivacy, VideoState } from '@shared/models'
import {
cleanupTests,
- createLive,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getVideoIdFromUUID,
- sendRTMPStreamInVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
- updateCustomSubConfig,
- viewVideo,
wait,
waitJobs,
- waitUntilLiveEnded,
waitUntilLivePublishedOnAllServers
} from '../../../../shared/extra-utils'
const expect = chai.expect
describe('Test live', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true,
+ transcoding: {
+ enabled: false
+ }
}
}
})
async function createLiveWrapper () {
const liveAttributes = {
name: 'live video',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC
}
- const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
- return res.body.video.uuid
+ const { uuid } = await servers[0].live.create({ fields: liveAttributes })
+ return uuid
}
it('Should correctly send a message when the live starts and ends', async function () {
await waitJobs(servers)
{
- const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID)
+ const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
- const localSocket = getLiveNotificationSocket(servers[0].url)
+ const localSocket = servers[0].socketIO.getLiveNotificationSocket()
localSocket.on('state-change', data => localStateChanges.push(data.state))
localSocket.emit('subscribe', { videoId })
}
{
- const videoId = await getVideoIdFromUUID(servers[1].url, liveVideoUUID)
+ const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
- const remoteSocket = getLiveNotificationSocket(servers[1].url)
+ const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
remoteSocket.on('state-change', data => remoteStateChanges.push(data.state))
remoteSocket.emit('subscribe', { videoId })
}
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
await waitJobs(servers)
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
}
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
for (const server of servers) {
- await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
+ await server.live.waitUntilEnded({ videoId: liveVideoUUID })
}
await waitJobs(servers)
await waitJobs(servers)
{
- const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID)
+ const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
- const localSocket = getLiveNotificationSocket(servers[0].url)
+ const localSocket = servers[0].socketIO.getLiveNotificationSocket()
localSocket.on('views-change', data => { localLastVideoViews = data.views })
localSocket.emit('subscribe', { videoId })
}
{
- const videoId = await getVideoIdFromUUID(servers[1].url, liveVideoUUID)
+ const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
- const remoteSocket = getLiveNotificationSocket(servers[1].url)
+ const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
remoteSocket.on('views-change', data => { remoteLastVideoViews = data.views })
remoteSocket.emit('subscribe', { videoId })
}
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
await waitJobs(servers)
expect(localLastVideoViews).to.equal(0)
expect(remoteLastVideoViews).to.equal(0)
- await viewVideo(servers[0].url, liveVideoUUID)
- await viewVideo(servers[1].url, liveVideoUUID)
+ await servers[0].videos.view({ id: liveVideoUUID })
+ await servers[1].videos.view({ id: liveVideoUUID })
await waitJobs(servers)
await wait(5000)
expect(localLastVideoViews).to.equal(2)
expect(remoteLastVideoViews).to.equal(2)
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
it('Should not receive a notification after unsubscribe', async function () {
const liveVideoUUID = await createLiveWrapper()
await waitJobs(servers)
- const videoId = await getVideoIdFromUUID(servers[0].url, liveVideoUUID)
+ const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
- const socket = getLiveNotificationSocket(servers[0].url)
+ const socket = servers[0].socketIO.getLiveNotificationSocket()
socket.on('state-change', data => stateChanges.push(data.state))
socket.emit('subscribe', { videoId })
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ const command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
import { FfmpegCommand } from 'fluent-ffmpeg'
-import { VideoDetails, VideoPrivacy } from '@shared/models'
+import { VideoPrivacy } from '@shared/models'
import {
cleanupTests,
- createLive,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getVideo,
- sendRTMPStreamInVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
- updateCustomSubConfig,
- viewVideo,
wait,
waitJobs,
waitUntilLivePublishedOnAllServers
const expect = chai.expect
describe('Test live', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true,
+ transcoding: {
+ enabled: false
+ }
}
}
})
async function countViews (expected: number) {
for (const server of servers) {
- const res = await getVideo(server.url, liveVideoId)
- const video: VideoDetails = res.body
-
+ const video = await server.videos.get({ id: liveVideoId })
expect(video.views).to.equal(expected)
}
}
const liveAttributes = {
name: 'live video',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC
}
- const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
- liveVideoId = res.body.video.uuid
+ const live = await servers[0].live.create({ fields: liveAttributes })
+ liveVideoId = live.uuid
- command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
+ command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
await waitJobs(servers)
})
it('Should view a live twice and display 1 view', async function () {
this.timeout(30000)
- await viewVideo(servers[0].url, liveVideoId)
- await viewVideo(servers[0].url, liveVideoId)
+ await servers[0].videos.view({ id: liveVideoId })
+ await servers[0].videos.view({ id: liveVideoId })
await wait(7000)
it('Should view a live on a remote and on local and display 2 views', async function () {
this.timeout(30000)
- await viewVideo(servers[0].url, liveVideoId)
- await viewVideo(servers[1].url, liveVideoId)
- await viewVideo(servers[1].url, liveVideoId)
+ await servers[0].videos.view({ id: liveVideoId })
+ await servers[1].videos.view({ id: liveVideoId })
+ await servers[1].videos.view({ id: liveVideoId })
await wait(7000)
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
-import { join } from 'path'
+import { basename, join } from 'path'
import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
-import { LiveVideo, LiveVideoCreate, Video, VideoDetails, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoToBlacklist,
- buildServerDirectory,
- checkLiveCleanup,
+ checkLiveCleanupAfterSave,
checkLiveSegmentHash,
checkResolutionsInMasterPlaylist,
cleanupTests,
- createLive,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getLive,
- getMyVideosWithFilter,
- getPlaylist,
- getVideo,
- getVideosList,
- getVideosWithFilters,
killallServers,
+ LiveCommand,
makeRawRequest,
- removeVideo,
- reRunServer,
+ PeerTubeServer,
sendRTMPStream,
- sendRTMPStreamInVideo,
- ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
testFfmpegStreamError,
testImage,
- updateCustomSubConfig,
- updateLive,
- uploadVideoAndGetId,
wait,
waitJobs,
- waitUntilLiveEnded,
- waitUntilLivePublished,
- waitUntilLivePublishedOnAllServers,
- waitUntilLiveSegmentGeneration
-} from '../../../../shared/extra-utils'
+ waitUntilLivePublishedOnAllServers
+} from '@shared/extra-utils'
+import {
+ HttpStatusCode,
+ LiveVideo,
+ LiveVideoCreate,
+ VideoDetails,
+ VideoPrivacy,
+ VideoState,
+ VideoStreamingPlaylistType
+} from '@shared/models'
const expect = chai.expect
describe('Test live', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
+ let commands: LiveCommand[]
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
+ enabled: true,
+ allowReplay: true,
+ transcoding: {
+ enabled: false
+ }
}
}
})
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
+
+ commands = servers.map(s => s.live)
})
describe('Live creation, update and delete', function () {
language: 'fr',
description: 'super live description',
support: 'support field',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
nsfw: false,
waitTranscoding: false,
name: 'my super live',
thumbnailfile: 'video_short1.webm.jpg'
}
- const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
- liveVideoUUID = res.body.video.uuid
+ const live = await commands[0].create({ fields: attributes })
+ liveVideoUUID = live.uuid
await waitJobs(servers)
for (const server of servers) {
- const resVideo = await getVideo(server.url, liveVideoUUID)
- const video: VideoDetails = resVideo.body
+ const video = await server.videos.get({ id: liveVideoUUID })
expect(video.category.id).to.equal(1)
expect(video.licence.id).to.equal(2)
expect(video.description).to.equal('super live description')
expect(video.support).to.equal('support field')
- expect(video.channel.name).to.equal(servers[0].videoChannel.name)
- expect(video.channel.host).to.equal(servers[0].videoChannel.host)
+ expect(video.channel.name).to.equal(servers[0].store.channel.name)
+ expect(video.channel.host).to.equal(servers[0].store.channel.host)
expect(video.isLive).to.be.true
await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
await testImage(server.url, 'video_short1.webm', video.thumbnailPath)
- const resLive = await getLive(server.url, server.accessToken, liveVideoUUID)
- const live: LiveVideo = resLive.body
+ const live = await server.live.get({ videoId: liveVideoUUID })
if (server.url === servers[0].url) {
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
const attributes: LiveVideoCreate = {
name: 'default live thumbnail',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.UNLISTED,
nsfw: true
}
- const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
- const videoId = res.body.video.uuid
+ const live = await commands[0].create({ fields: attributes })
+ const videoId = live.uuid
await waitJobs(servers)
for (const server of servers) {
- const resVideo = await getVideo(server.url, videoId)
- const video: VideoDetails = resVideo.body
-
+ const video = await server.videos.get({ id: videoId })
expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
expect(video.nsfw).to.be.true
it('Should not have the live listed since nobody streams into', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
}
})
it('Should not be able to update a live of another server', async function () {
- await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
+ await commands[1].update({ videoId: liveVideoUUID, fields: { saveReplay: false }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should update the live', async function () {
this.timeout(10000)
- await updateLive(servers[0].url, servers[0].accessToken, liveVideoUUID, { saveReplay: false })
+ await commands[0].update({ videoId: liveVideoUUID, fields: { saveReplay: false } })
await waitJobs(servers)
})
it('Have the live updated', async function () {
for (const server of servers) {
- const res = await getLive(server.url, server.accessToken, liveVideoUUID)
- const live: LiveVideo = res.body
+ const live = await server.live.get({ videoId: liveVideoUUID })
if (server.url === servers[0].url) {
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
it('Delete the live', async function () {
this.timeout(10000)
- await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ await servers[0].videos.remove({ id: liveVideoUUID })
await waitJobs(servers)
})
it('Should have the live deleted', async function () {
for (const server of servers) {
- await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
- await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
+ await server.videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await server.live.get({ videoId: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
})
})
describe('Live filters', function () {
- let command: any
+ let ffmpegCommand: any
let liveVideoId: string
let vodVideoId: string
before(async function () {
this.timeout(120000)
- vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid
+ vodVideoId = (await servers[0].videos.quickUpload({ name: 'vod video' })).uuid
- const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id }
- const resLive = await createLive(servers[0].url, servers[0].accessToken, liveOptions)
- liveVideoId = resLive.body.video.uuid
+ const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].store.channel.id }
+ const live = await commands[0].create({ fields: liveOptions })
+ liveVideoId = live.uuid
- command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
+ ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
await waitJobs(servers)
})
it('Should only display lives', async function () {
- const res = await getVideosWithFilters(servers[0].url, { isLive: true })
+ const { data, total } = await servers[0].videos.list({ isLive: true })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('live')
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('live')
})
it('Should not display lives', async function () {
- const res = await getVideosWithFilters(servers[0].url, { isLive: false })
+ const { data, total } = await servers[0].videos.list({ isLive: false })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('vod video')
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('vod video')
})
it('Should display my lives', async function () {
this.timeout(60000)
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
await waitJobs(servers)
- const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true })
- const videos = res.body.data as Video[]
+ const { data } = await servers[0].videos.listMyVideos({ isLive: true })
- const result = videos.every(v => v.isLive)
+ const result = data.every(v => v.isLive)
expect(result).to.be.true
})
it('Should not display my lives', async function () {
- const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: false })
- const videos = res.body.data as Video[]
+ const { data } = await servers[0].videos.listMyVideos({ isLive: false })
- const result = videos.every(v => !v.isLive)
+ const result = data.every(v => !v.isLive)
expect(result).to.be.true
})
after(async function () {
- await removeVideo(servers[0].url, servers[0].accessToken, vodVideoId)
- await removeVideo(servers[0].url, servers[0].accessToken, liveVideoId)
+ await servers[0].videos.remove({ id: vodVideoId })
+ await servers[0].videos.remove({ id: liveVideoId })
})
})
async function createLiveWrapper () {
const liveAttributes = {
name: 'user live',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC,
saveReplay: false
}
- const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
- const uuid = res.body.video.uuid
+ const { uuid } = await commands[0].create({ fields: liveAttributes })
- const resLive = await getLive(servers[0].url, servers[0].accessToken, uuid)
- const resVideo = await getVideo(servers[0].url, uuid)
+ const live = await commands[0].get({ videoId: uuid })
+ const video = await servers[0].videos.get({ id: uuid })
- return Object.assign(resVideo.body, resLive.body) as LiveVideo & VideoDetails
+ return Object.assign(video, live)
}
it('Should not allow a stream without the appropriate path', async function () {
it('Should list this live now someone stream into it', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
-
- const video: Video = res.body.data[0]
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ const video = data[0]
expect(video.name).to.equal('user live')
expect(video.isLive).to.be.true
}
liveVideo = await createLiveWrapper()
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideo.uuid)
+ await servers[0].blacklist.add({ videoId: liveVideo.uuid })
const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey)
await testFfmpegStreamError(command, true)
liveVideo = await createLiveWrapper()
- await removeVideo(servers[0].url, servers[0].accessToken, liveVideo.uuid)
+ await servers[0].videos.remove({ id: liveVideo.uuid })
const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey)
await testFfmpegStreamError(command, true)
async function createLiveWrapper (saveReplay: boolean) {
const liveAttributes = {
name: 'live video',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC,
saveReplay
}
- const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
- return res.body.video.uuid
+ const { uuid } = await commands[0].create({ fields: liveAttributes })
+ return uuid
}
async function testVideoResolutions (liveVideoId: string, resolutions: number[]) {
for (const server of servers) {
- const resList = await getVideosList(server.url)
- const videos: Video[] = resList.body.data
-
- expect(videos.find(v => v.uuid === liveVideoId)).to.exist
+ const { data } = await server.videos.list()
+ expect(data.find(v => v.uuid === liveVideoId)).to.exist
- const resVideo = await getVideo(server.url, liveVideoId)
- const video: VideoDetails = resVideo.body
+ const video = await server.videos.get({ id: liveVideoId })
expect(video.streamingPlaylists).to.have.lengthOf(1)
// Only finite files are displayed
expect(hlsPlaylist.files).to.have.lengthOf(0)
- await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions)
+ await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions })
for (let i = 0; i < resolutions.length; i++) {
const segmentNum = 3
const segmentName = `${i}-00000${segmentNum}.ts`
- await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum)
+ await commands[0].waitUntilSegmentGeneration({ videoUUID: video.uuid, resolution: i, segment: segmentNum })
- const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`)
- const subPlaylist = res.text
+ const subPlaylist = await servers[0].streamingPlaylists.get({
+ url: `${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`
+ })
expect(subPlaylist).to.contain(segmentName)
const baseUrlAndPath = servers[0].url + '/static/streaming-playlists/hls'
- await checkLiveSegmentHash(baseUrlAndPath, video.uuid, segmentName, hlsPlaylist)
+ await checkLiveSegmentHash({
+ server,
+ baseUrlSegment: baseUrlAndPath,
+ videoUUID: video.uuid,
+ segmentName,
+ hlsPlaylist
+ })
}
}
}
function updateConf (resolutions: number[]) {
- return updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
+ return servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: {
enabled: true,
- resolutions: {
- '240p': resolutions.includes(240),
- '360p': resolutions.includes(360),
- '480p': resolutions.includes(480),
- '720p': resolutions.includes(720),
- '1080p': resolutions.includes(1080),
- '2160p': resolutions.includes(2160)
+ allowReplay: true,
+ maxDuration: -1,
+ transcoding: {
+ enabled: true,
+ resolutions: {
+ '240p': resolutions.includes(240),
+ '360p': resolutions.includes(360),
+ '480p': resolutions.includes(480),
+ '720p': resolutions.includes(720),
+ '1080p': resolutions.includes(1080),
+ '2160p': resolutions.includes(2160)
+ }
}
}
}
liveVideoId = await createLiveWrapper(false)
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
+ const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, [ 720 ])
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
it('Should enable transcoding with some resolutions', async function () {
await updateConf(resolutions)
liveVideoId = await createLiveWrapper(false)
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
+ const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
})
it('Should enable transcoding with some resolutions and correctly save them', async function () {
await updateConf(resolutions)
liveVideoId = await createLiveWrapper(true)
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm')
+ const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
- await stopFfmpeg(command)
- await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
+ await stopFfmpeg(ffmpegCommand)
+ await commands[0].waitUntilEnded({ videoId: liveVideoId })
await waitJobs(servers)
}
for (const server of servers) {
- const resVideo = await getVideo(server.url, liveVideoId)
- const video: VideoDetails = resVideo.body
+ const video = await server.videos.get({ id: liveVideoId })
expect(video.state.id).to.equal(VideoState.PUBLISHED)
expect(video.duration).to.be.greaterThan(1)
await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
+ // We should have generated random filenames
+ expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8')
+ expect(basename(hlsPlaylist.segmentsSha256Url)).to.not.equal('segments-sha256.json')
+
expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
for (const resolution of resolutions) {
expect(file.fps).to.be.approximately(30, 2)
}
- const filename = `${video.uuid}-${resolution}-fragmented.mp4`
- const segmentPath = buildServerDirectory(servers[0], join('streaming-playlists', 'hls', video.uuid, filename))
+ const filename = basename(file.fileUrl)
+ expect(filename).to.not.contain(video.uuid)
+
+ const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename))
const probe = await ffprobePromise(segmentPath)
const videoStream = await getVideoStreamFromFile(segmentPath, probe)
it('Should correctly have cleaned up the live files', async function () {
this.timeout(30000)
- await checkLiveCleanup(servers[0], liveVideoId, [ 240, 360, 720 ])
+ await checkLiveCleanupAfterSave(servers[0], liveVideoId, [ 240, 360, 720 ])
})
})
async function createLiveWrapper (saveReplay: boolean) {
const liveAttributes = {
name: 'live video',
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
privacy: VideoPrivacy.PUBLIC,
saveReplay
}
- const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
- return res.body.video.uuid
+ const { uuid } = await commands[0].create({ fields: liveAttributes })
+ return uuid
}
before(async function () {
liveVideoReplayId = await createLiveWrapper(true)
await Promise.all([
- sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId),
- sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoReplayId)
+ commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }),
+ commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId })
])
await Promise.all([
- waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId),
- waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
+ commands[0].waitUntilPublished({ videoId: liveVideoId }),
+ commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
])
- await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2)
- await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2)
+ await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 })
+ await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 })
await killallServers([ servers[0] ])
- await reRunServer(servers[0])
+ await servers[0].run()
await wait(5000)
})
it('Should cleanup lives', async function () {
this.timeout(60000)
- await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
+ await commands[0].waitUntilEnded({ videoId: liveVideoId })
})
it('Should save a live replay', async function () {
this.timeout(120000)
- await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
+ await commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
})
})
import 'mocha'
import * as chai from 'chai'
import {
- AbuseFilter,
- AbuseMessage,
- AbusePredefinedReasonsString,
- AbuseState,
- Account,
- AdminAbuse,
- UserAbuse,
- VideoComment
-} from '@shared/models'
-import {
- addAbuseMessage,
- addVideoCommentThread,
+ AbusesCommand,
cleanupTests,
- createUser,
- deleteAbuse,
- deleteAbuseMessage,
- deleteVideoComment,
- flushAndRunMultipleServers,
- generateUserAccessToken,
- getAccount,
- getAdminAbusesList,
- getUserAbusesList,
- getVideoCommentThreads,
- getVideoIdFromUUID,
- getVideosList,
- immutableAssign,
- listAbuseMessages,
- removeUser,
- removeVideo,
- reportAbuse,
- ServerInfo,
+ createMultipleServers,
+ doubleFollow,
+ PeerTubeServer,
setAccessTokensToServers,
- updateAbuse,
- uploadVideo,
- uploadVideoAndGetId,
- userLogin
-} from '../../../../shared/extra-utils/index'
-import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- addAccountToServerBlocklist,
- addServerToServerBlocklist,
- removeAccountFromServerBlocklist,
- removeServerFromServerBlocklist
-} from '../../../../shared/extra-utils/users/blocklist'
+ waitJobs
+} from '@shared/extra-utils'
+import { AbuseMessage, AbusePredefinedReasonsString, AbuseState, AdminAbuse, UserAbuse } from '@shared/models'
const expect = chai.expect
describe('Test abuses', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let abuseServer1: AdminAbuse
let abuseServer2: AdminAbuse
+ let commands: AbusesCommand[]
before(async function () {
this.timeout(50000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
+
+ commands = servers.map(s => s.abuses)
})
describe('Video abuses', function () {
this.timeout(50000)
// Upload some videos on each servers
- const video1Attributes = {
- name: 'my super name for server 1',
- description: 'my super description for server 1'
+ {
+ const attributes = {
+ name: 'my super name for server 1',
+ description: 'my super description for server 1'
+ }
+ await servers[0].videos.upload({ attributes })
}
- await uploadVideo(servers[0].url, servers[0].accessToken, video1Attributes)
- const video2Attributes = {
- name: 'my super name for server 2',
- description: 'my super description for server 2'
+ {
+ const attributes = {
+ name: 'my super name for server 2',
+ description: 'my super description for server 2'
+ }
+ await servers[1].videos.upload({ attributes })
}
- await uploadVideo(servers[1].url, servers[1].accessToken, video2Attributes)
// Wait videos propagation, server 2 has transcoding enabled
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
+ expect(data.length).to.equal(2)
- expect(videos.length).to.equal(2)
-
- servers[0].video = videos.find(video => video.name === 'my super name for server 1')
- servers[1].video = videos.find(video => video.name === 'my super name for server 2')
+ servers[0].store.videoCreated = data.find(video => video.name === 'my super name for server 1')
+ servers[1].store.videoCreated = data.find(video => video.name === 'my super name for server 2')
})
it('Should not have abuses', async function () {
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
+ const body = await commands[0].getAdminList()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
})
it('Should report abuse on a local video', async function () {
this.timeout(15000)
const reason = 'my super bad reason'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: servers[0].video.id, reason })
+ await commands[0].report({ videoId: servers[0].store.videoCreated.id, reason })
// We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
await waitJobs(servers)
})
it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
- const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
+ {
+ const body = await commands[0].getAdminList()
- expect(res1.body.total).to.equal(1)
- expect(res1.body.data).to.be.an('array')
- expect(res1.body.data.length).to.equal(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(1)
- const abuse: AdminAbuse = res1.body.data[0]
- expect(abuse.reason).to.equal('my super bad reason')
+ const abuse = body.data[0]
+ expect(abuse.reason).to.equal('my super bad reason')
- expect(abuse.reporterAccount.name).to.equal('root')
- expect(abuse.reporterAccount.host).to.equal(servers[0].host)
+ expect(abuse.reporterAccount.name).to.equal('root')
+ expect(abuse.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse.video.id).to.equal(servers[0].video.id)
- expect(abuse.video.channel).to.exist
+ expect(abuse.video.id).to.equal(servers[0].store.videoCreated.id)
+ expect(abuse.video.channel).to.exist
- expect(abuse.comment).to.be.null
+ expect(abuse.comment).to.be.null
- expect(abuse.flaggedAccount.name).to.equal('root')
- expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
+ expect(abuse.flaggedAccount.name).to.equal('root')
+ expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
- expect(abuse.video.countReports).to.equal(1)
- expect(abuse.video.nthReport).to.equal(1)
+ expect(abuse.video.countReports).to.equal(1)
+ expect(abuse.video.nthReport).to.equal(1)
- expect(abuse.countReportsForReporter).to.equal(1)
- expect(abuse.countReportsForReportee).to.equal(1)
+ expect(abuse.countReportsForReporter).to.equal(1)
+ expect(abuse.countReportsForReportee).to.equal(1)
+ }
- const res2 = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
- expect(res2.body.total).to.equal(0)
- expect(res2.body.data).to.be.an('array')
- expect(res2.body.data.length).to.equal(0)
+ {
+ const body = await commands[1].getAdminList()
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
})
it('Should report abuse on a remote video', async function () {
this.timeout(10000)
const reason = 'my super bad reason 2'
- const videoId = await getVideoIdFromUUID(servers[0].url, servers[1].video.uuid)
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId, reason })
+ const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
+ await commands[0].report({ videoId, reason })
// We wait requests propagation
await waitJobs(servers)
})
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
- const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
+ {
+ const body = await commands[0].getAdminList()
- expect(res1.body.total).to.equal(2)
- expect(res1.body.data.length).to.equal(2)
+ expect(body.total).to.equal(2)
+ expect(body.data.length).to.equal(2)
- const abuse1: AdminAbuse = res1.body.data[0]
- expect(abuse1.reason).to.equal('my super bad reason')
- expect(abuse1.reporterAccount.name).to.equal('root')
- expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
+ const abuse1 = body.data[0]
+ expect(abuse1.reason).to.equal('my super bad reason')
+ expect(abuse1.reporterAccount.name).to.equal('root')
+ expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse1.video.id).to.equal(servers[0].video.id)
- expect(abuse1.video.countReports).to.equal(1)
- expect(abuse1.video.nthReport).to.equal(1)
+ expect(abuse1.video.id).to.equal(servers[0].store.videoCreated.id)
+ expect(abuse1.video.countReports).to.equal(1)
+ expect(abuse1.video.nthReport).to.equal(1)
- expect(abuse1.comment).to.be.null
+ expect(abuse1.comment).to.be.null
- expect(abuse1.flaggedAccount.name).to.equal('root')
- expect(abuse1.flaggedAccount.host).to.equal(servers[0].host)
+ expect(abuse1.flaggedAccount.name).to.equal('root')
+ expect(abuse1.flaggedAccount.host).to.equal(servers[0].host)
- expect(abuse1.state.id).to.equal(AbuseState.PENDING)
- expect(abuse1.state.label).to.equal('Pending')
- expect(abuse1.moderationComment).to.be.null
+ expect(abuse1.state.id).to.equal(AbuseState.PENDING)
+ expect(abuse1.state.label).to.equal('Pending')
+ expect(abuse1.moderationComment).to.be.null
- const abuse2: AdminAbuse = res1.body.data[1]
- expect(abuse2.reason).to.equal('my super bad reason 2')
+ const abuse2 = body.data[1]
+ expect(abuse2.reason).to.equal('my super bad reason 2')
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
+ expect(abuse2.reporterAccount.name).to.equal('root')
+ expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse2.video.id).to.equal(servers[1].video.id)
+ expect(abuse2.video.id).to.equal(servers[1].store.videoCreated.id)
- expect(abuse2.comment).to.be.null
+ expect(abuse2.comment).to.be.null
- expect(abuse2.flaggedAccount.name).to.equal('root')
- expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
+ expect(abuse2.flaggedAccount.name).to.equal('root')
+ expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
- expect(abuse2.moderationComment).to.be.null
+ expect(abuse2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuse2.state.label).to.equal('Pending')
+ expect(abuse2.moderationComment).to.be.null
+ }
- const res2 = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
- expect(res2.body.total).to.equal(1)
- expect(res2.body.data.length).to.equal(1)
+ {
+ const body = await commands[1].getAdminList()
+ expect(body.total).to.equal(1)
+ expect(body.data.length).to.equal(1)
- abuseServer2 = res2.body.data[0]
- expect(abuseServer2.reason).to.equal('my super bad reason 2')
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
+ abuseServer2 = body.data[0]
+ expect(abuseServer2.reason).to.equal('my super bad reason 2')
+ expect(abuseServer2.reporterAccount.name).to.equal('root')
+ expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse2.flaggedAccount.name).to.equal('root')
- expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
+ expect(abuseServer2.flaggedAccount.name).to.equal('root')
+ expect(abuseServer2.flaggedAccount.host).to.equal(servers[1].host)
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
- expect(abuseServer2.moderationComment).to.be.null
+ expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuseServer2.state.label).to.equal('Pending')
+ expect(abuseServer2.moderationComment).to.be.null
+ }
})
it('Should hide video abuses from blocked accounts', async function () {
this.timeout(10000)
{
- const videoId = await getVideoIdFromUUID(servers[1].url, servers[0].video.uuid)
- await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'will mute this' })
+ const videoId = await servers[1].videos.getId({ uuid: servers[0].store.videoCreated.uuid })
+ await commands[1].report({ videoId, reason: 'will mute this' })
await waitJobs(servers)
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(3)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(3)
}
const accountToBlock = 'root@' + servers[1].host
{
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
+ await servers[0].blocklist.addToServerBlocklist({ account: accountToBlock })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(2)
- const abuse = res.body.data.find(a => a.reason === 'will mute this')
+ const abuse = body.data.find(a => a.reason === 'will mute this')
expect(abuse).to.be.undefined
}
{
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
+ await servers[0].blocklist.removeFromServerBlocklist({ account: accountToBlock })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(3)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(3)
}
})
const serverToBlock = servers[1].host
{
- await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
+ await servers[0].blocklist.addToServerBlocklist({ server: serverToBlock })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(2)
- const abuse = res.body.data.find(a => a.reason === 'will mute this')
+ const abuse = body.data.find(a => a.reason === 'will mute this')
expect(abuse).to.be.undefined
}
{
- await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
+ await servers[0].blocklist.removeFromServerBlocklist({ server: serverToBlock })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(3)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(3)
}
})
it('Should keep the video abuse when deleting the video', async function () {
this.timeout(10000)
- await removeVideo(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid)
+ await servers[1].videos.remove({ id: abuseServer2.video.uuid })
await waitJobs(servers)
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
- expect(res.body.total).to.equal(2, "wrong number of videos returned")
- expect(res.body.data).to.have.lengthOf(2, "wrong number of videos returned")
+ const body = await commands[1].getAdminList()
+ expect(body.total).to.equal(2, "wrong number of videos returned")
+ expect(body.data).to.have.lengthOf(2, "wrong number of videos returned")
- const abuse: AdminAbuse = res.body.data[0]
+ const abuse = body.data[0]
expect(abuse.id).to.equal(abuseServer2.id, "wrong origin server id for first video")
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
expect(abuse.video.channel).to.exist
// register a second user to have two reporters/reportees
const user = { username: 'user2', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, ...user })
- const userAccessToken = await userLogin(servers[0], user)
+ await servers[0].users.create({ ...user })
+ const userAccessToken = await servers[0].login.getAccessToken(user)
// upload a third video via this user
- const video3Attributes = {
+ const attributes = {
name: 'my second super name for server 1',
description: 'my second super description for server 1'
}
- await uploadVideo(servers[0].url, userAccessToken, video3Attributes)
-
- const res1 = await getVideosList(servers[0].url)
- const videos = res1.body.data
- const video3 = videos.find(video => video.name === 'my second super name for server 1')
+ const { id } = await servers[0].videos.upload({ token: userAccessToken, attributes })
+ const video3Id = id
// resume with the test
const reason3 = 'my super bad reason 3'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: video3.id, reason: reason3 })
+ await commands[0].report({ videoId: video3Id, reason: reason3 })
const reason4 = 'my super bad reason 4'
- await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: reason4 })
+ await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: reason4 })
{
- const res2 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- const abuses = res2.body.data as AdminAbuse[]
+ const body = await commands[0].getAdminList()
+ const abuses = body.data
- const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
+ const abuseVideo3 = body.data.find(a => a.video.id === video3Id)
expect(abuseVideo3).to.not.be.undefined
expect(abuseVideo3.video.countReports).to.equal(1, "wrong reports count for video 3")
expect(abuseVideo3.video.nthReport).to.equal(1, "wrong report position in report list for video 3")
expect(abuseVideo3.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
expect(abuseVideo3.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
- const abuseServer1 = abuses.find(a => a.video.id === servers[0].video.id)
+ const abuseServer1 = abuses.find(a => a.video.id === servers[0].store.videoCreated.id)
expect(abuseServer1.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse")
}
})
const reason5 = 'my super bad reason 5'
const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
- const createdAbuse = (await reportAbuse({
- url: servers[0].url,
- token: servers[0].accessToken,
- videoId: servers[0].video.id,
+ const createRes = await commands[0].report({
+ videoId: servers[0].store.videoCreated.id,
reason: reason5,
predefinedReasons: predefinedReasons5,
startAt: 1,
endAt: 5
- })).body.abuse
+ })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
+ const body = await commands[0].getAdminList()
{
- const abuse = (res.body.data as AdminAbuse[]).find(a => a.id === createdAbuse.id)
+ const abuse = body.data.find(a => a.id === createRes.abuse.id)
expect(abuse.reason).to.equals(reason5)
expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported")
it('Should delete the video abuse', async function () {
this.timeout(10000)
- await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
+ await commands[1].delete({ abuseId: abuseServer2.id })
await waitJobs(servers)
{
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
- expect(res.body.total).to.equal(1)
- expect(res.body.data.length).to.equal(1)
- expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
+ const body = await commands[1].getAdminList()
+ expect(body.total).to.equal(1)
+ expect(body.data.length).to.equal(1)
+ expect(body.data[0].id).to.not.equal(abuseServer2.id)
}
{
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(6)
+ const body = await commands[0].getAdminList()
+ expect(body.total).to.equal(6)
}
})
it('Should list and filter video abuses', async function () {
this.timeout(10000)
- async function list (query: Omit<Parameters<typeof getAdminAbusesList>[0], 'url' | 'token'>) {
- const options = {
- url: servers[0].url,
- token: servers[0].accessToken
- }
-
- Object.assign(options, query)
+ async function list (query: Parameters<AbusesCommand['getAdminList']>[0]) {
+ const body = await commands[0].getAdminList(query)
- const res = await getAdminAbusesList(options)
-
- return res.body.data as AdminAbuse[]
+ return body.data
}
expect(await list({ id: 56 })).to.have.lengthOf(0)
describe('Comment abuses', function () {
- async function getComment (url: string, videoIdArg: number | string) {
+ async function getComment (server: PeerTubeServer, videoIdArg: number | string) {
const videoId = typeof videoIdArg === 'string'
- ? await getVideoIdFromUUID(url, videoIdArg)
+ ? await server.videos.getId({ uuid: videoIdArg })
: videoIdArg
- const res = await getVideoCommentThreads(url, videoId, 0, 5)
+ const { data } = await server.comments.listThreads({ videoId })
- return res.body.data[0] as VideoComment
+ return data[0]
}
before(async function () {
this.timeout(50000)
- servers[0].video = await uploadVideoAndGetId({ server: servers[0], videoName: 'server 1' })
- servers[1].video = await uploadVideoAndGetId({ server: servers[1], videoName: 'server 2' })
+ servers[0].store.videoCreated = await servers[0].videos.quickUpload({ name: 'server 1' })
+ servers[1].store.videoCreated = await servers[1].videos.quickUpload({ name: 'server 2' })
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, servers[0].video.id, 'comment server 1')
- await addVideoCommentThread(servers[1].url, servers[1].accessToken, servers[1].video.id, 'comment server 2')
+ await servers[0].comments.createThread({ videoId: servers[0].store.videoCreated.id, text: 'comment server 1' })
+ await servers[1].comments.createThread({ videoId: servers[1].store.videoCreated.id, text: 'comment server 2' })
await waitJobs(servers)
})
it('Should report abuse on a comment', async function () {
this.timeout(15000)
- const comment = await getComment(servers[0].url, servers[0].video.id)
+ const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
const reason = 'it is a bad comment'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason })
+ await commands[0].report({ commentId: comment.id, reason })
await waitJobs(servers)
})
it('Should have 1 comment abuse on server 1 and 0 on server 2', async function () {
{
- const comment = await getComment(servers[0].url, servers[0].video.id)
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
+ const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
+ const body = await commands[0].getAdminList({ filter: 'comment' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const abuse: AdminAbuse = res.body.data[0]
+ const abuse = body.data[0]
expect(abuse.reason).to.equal('it is a bad comment')
expect(abuse.reporterAccount.name).to.equal('root')
expect(abuse.comment.id).to.equal(comment.id)
expect(abuse.comment.text).to.equal(comment.text)
expect(abuse.comment.video.name).to.equal('server 1')
- expect(abuse.comment.video.id).to.equal(servers[0].video.id)
- expect(abuse.comment.video.uuid).to.equal(servers[0].video.uuid)
+ expect(abuse.comment.video.id).to.equal(servers[0].store.videoCreated.id)
+ expect(abuse.comment.video.uuid).to.equal(servers[0].store.videoCreated.uuid)
expect(abuse.countReportsForReporter).to.equal(5)
expect(abuse.countReportsForReportee).to.equal(5)
}
{
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data.length).to.equal(0)
+ const body = await commands[1].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(0)
+ expect(body.data.length).to.equal(0)
}
})
it('Should report abuse on a remote comment', async function () {
this.timeout(10000)
- const comment = await getComment(servers[0].url, servers[1].video.uuid)
+ const comment = await getComment(servers[0], servers[1].store.videoCreated.uuid)
const reason = 'it is a really bad comment'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason })
+ await commands[0].report({ commentId: comment.id, reason })
await waitJobs(servers)
})
it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
- const commentServer2 = await getComment(servers[0].url, servers[1].video.id)
+ const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.id)
- const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
- expect(res1.body.total).to.equal(2)
- expect(res1.body.data.length).to.equal(2)
+ {
+ const body = await commands[0].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(2)
+ expect(body.data.length).to.equal(2)
- const abuse: AdminAbuse = res1.body.data[0]
- expect(abuse.reason).to.equal('it is a bad comment')
- expect(abuse.countReportsForReporter).to.equal(6)
- expect(abuse.countReportsForReportee).to.equal(5)
+ const abuse = body.data[0]
+ expect(abuse.reason).to.equal('it is a bad comment')
+ expect(abuse.countReportsForReporter).to.equal(6)
+ expect(abuse.countReportsForReportee).to.equal(5)
- const abuse2: AdminAbuse = res1.body.data[1]
+ const abuse2 = body.data[1]
- expect(abuse2.reason).to.equal('it is a really bad comment')
+ expect(abuse2.reason).to.equal('it is a really bad comment')
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
+ expect(abuse2.reporterAccount.name).to.equal('root')
+ expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse2.video).to.be.null
+ expect(abuse2.video).to.be.null
- expect(abuse2.comment.deleted).to.be.false
- expect(abuse2.comment.id).to.equal(commentServer2.id)
- expect(abuse2.comment.text).to.equal(commentServer2.text)
- expect(abuse2.comment.video.name).to.equal('server 2')
- expect(abuse2.comment.video.uuid).to.equal(servers[1].video.uuid)
+ expect(abuse2.comment.deleted).to.be.false
+ expect(abuse2.comment.id).to.equal(commentServer2.id)
+ expect(abuse2.comment.text).to.equal(commentServer2.text)
+ expect(abuse2.comment.video.name).to.equal('server 2')
+ expect(abuse2.comment.video.uuid).to.equal(servers[1].store.videoCreated.uuid)
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
+ expect(abuse2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuse2.state.label).to.equal('Pending')
- expect(abuse2.moderationComment).to.be.null
+ expect(abuse2.moderationComment).to.be.null
- expect(abuse2.countReportsForReporter).to.equal(6)
- expect(abuse2.countReportsForReportee).to.equal(2)
+ expect(abuse2.countReportsForReporter).to.equal(6)
+ expect(abuse2.countReportsForReportee).to.equal(2)
+ }
- const res2 = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
- expect(res2.body.total).to.equal(1)
- expect(res2.body.data.length).to.equal(1)
+ {
+ const body = await commands[1].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(1)
+ expect(body.data.length).to.equal(1)
- abuseServer2 = res2.body.data[0]
- expect(abuseServer2.reason).to.equal('it is a really bad comment')
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
+ abuseServer2 = body.data[0]
+ expect(abuseServer2.reason).to.equal('it is a really bad comment')
+ expect(abuseServer2.reporterAccount.name).to.equal('root')
+ expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
+ expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuseServer2.state.label).to.equal('Pending')
- expect(abuseServer2.moderationComment).to.be.null
+ expect(abuseServer2.moderationComment).to.be.null
- expect(abuseServer2.countReportsForReporter).to.equal(1)
- expect(abuseServer2.countReportsForReportee).to.equal(1)
+ expect(abuseServer2.countReportsForReporter).to.equal(1)
+ expect(abuseServer2.countReportsForReportee).to.equal(1)
+ }
})
it('Should keep the comment abuse when deleting the comment', async function () {
this.timeout(10000)
- const commentServer2 = await getComment(servers[0].url, servers[1].video.id)
+ const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.id)
- await deleteVideoComment(servers[0].url, servers[0].accessToken, servers[1].video.uuid, commentServer2.id)
+ await servers[0].comments.delete({ videoId: servers[1].store.videoCreated.uuid, commentId: commentServer2.id })
await waitJobs(servers)
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await commands[0].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
- const abuse = (res.body.data as AdminAbuse[]).find(a => a.comment?.id === commentServer2.id)
+ const abuse = body.data.find(a => a.comment?.id === commentServer2.id)
expect(abuse).to.not.be.undefined
expect(abuse.comment.text).to.be.empty
it('Should delete the comment abuse', async function () {
this.timeout(10000)
- await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
+ await commands[1].delete({ abuseId: abuseServer2.id })
await waitJobs(servers)
{
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data.length).to.equal(0)
+ const body = await commands[1].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(0)
+ expect(body.data.length).to.equal(0)
}
{
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(2)
}
})
it('Should list and filter video abuses', async function () {
{
- const res = await getAdminAbusesList({
- url: servers[0].url,
- token: servers[0].accessToken,
- filter: 'comment',
- searchReportee: 'foo'
- })
- expect(res.body.total).to.equal(0)
+ const body = await commands[0].getAdminList({ filter: 'comment', searchReportee: 'foo' })
+ expect(body.total).to.equal(0)
}
{
- const res = await getAdminAbusesList({
- url: servers[0].url,
- token: servers[0].accessToken,
- filter: 'comment',
- searchReportee: 'ot'
- })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getAdminList({ filter: 'comment', searchReportee: 'ot' })
+ expect(body.total).to.equal(2)
}
{
- const baseParams = { url: servers[0].url, token: servers[0].accessToken, filter: 'comment' as AbuseFilter, start: 1, count: 1 }
-
- const res1 = await getAdminAbusesList(immutableAssign(baseParams, { sort: 'createdAt' }))
- expect(res1.body.data).to.have.lengthOf(1)
- expect(res1.body.data[0].comment.text).to.be.empty
+ const body = await commands[0].getAdminList({ filter: 'comment', start: 1, count: 1, sort: 'createdAt' })
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].comment.text).to.be.empty
+ }
- const res2 = await getAdminAbusesList(immutableAssign(baseParams, { sort: '-createdAt' }))
- expect(res2.body.data).to.have.lengthOf(1)
- expect(res2.body.data[0].comment.text).to.equal('comment server 1')
+ {
+ const body = await commands[0].getAdminList({ filter: 'comment', start: 1, count: 1, sort: '-createdAt' })
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].comment.text).to.equal('comment server 1')
}
})
})
describe('Account abuses', function () {
- async function getAccountFromServer (url: string, name: string, server: ServerInfo) {
- const res = await getAccount(url, name + '@' + server.host)
-
- return res.body as Account
+ function getAccountFromServer (server: PeerTubeServer, targetName: string, targetServer: PeerTubeServer) {
+ return server.accounts.get({ accountName: targetName + '@' + targetServer.host })
}
before(async function () {
this.timeout(50000)
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: 'user_1', password: 'donald' })
+ await servers[0].users.create({ username: 'user_1', password: 'donald' })
- const token = await generateUserAccessToken(servers[1], 'user_2')
- await uploadVideo(servers[1].url, token, { name: 'super video' })
+ const token = await servers[1].users.generateUserAndToken('user_2')
+ await servers[1].videos.upload({ token, attributes: { name: 'super video' } })
await waitJobs(servers)
})
it('Should report abuse on an account', async function () {
this.timeout(15000)
- const account = await getAccountFromServer(servers[0].url, 'user_1', servers[0])
+ const account = await getAccountFromServer(servers[0], 'user_1', servers[0])
const reason = 'it is a bad account'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId: account.id, reason })
+ await commands[0].report({ accountId: account.id, reason })
await waitJobs(servers)
})
it('Should have 1 account abuse on server 1 and 0 on server 2', async function () {
{
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
+ const body = await commands[0].getAdminList({ filter: 'account' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const abuse: AdminAbuse = res.body.data[0]
+ const abuse = body.data[0]
expect(abuse.reason).to.equal('it is a bad account')
expect(abuse.reporterAccount.name).to.equal('root')
}
{
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data.length).to.equal(0)
+ const body = await commands[1].getAdminList({ filter: 'comment' })
+ expect(body.total).to.equal(0)
+ expect(body.data.length).to.equal(0)
}
})
it('Should report abuse on a remote account', async function () {
this.timeout(10000)
- const account = await getAccountFromServer(servers[0].url, 'user_2', servers[1])
+ const account = await getAccountFromServer(servers[0], 'user_2', servers[1])
const reason = 'it is a really bad account'
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId: account.id, reason })
+ await commands[0].report({ accountId: account.id, reason })
await waitJobs(servers)
})
it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
- const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
- expect(res1.body.total).to.equal(2)
- expect(res1.body.data.length).to.equal(2)
+ {
+ const body = await commands[0].getAdminList({ filter: 'account' })
+ expect(body.total).to.equal(2)
+ expect(body.data.length).to.equal(2)
- const abuse: AdminAbuse = res1.body.data[0]
- expect(abuse.reason).to.equal('it is a bad account')
+ const abuse: AdminAbuse = body.data[0]
+ expect(abuse.reason).to.equal('it is a bad account')
- const abuse2: AdminAbuse = res1.body.data[1]
- expect(abuse2.reason).to.equal('it is a really bad account')
+ const abuse2: AdminAbuse = body.data[1]
+ expect(abuse2.reason).to.equal('it is a really bad account')
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
+ expect(abuse2.reporterAccount.name).to.equal('root')
+ expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuse2.video).to.be.null
- expect(abuse2.comment).to.be.null
+ expect(abuse2.video).to.be.null
+ expect(abuse2.comment).to.be.null
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
+ expect(abuse2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuse2.state.label).to.equal('Pending')
- expect(abuse2.moderationComment).to.be.null
+ expect(abuse2.moderationComment).to.be.null
+ }
- const res2 = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
- expect(res2.body.total).to.equal(1)
- expect(res2.body.data.length).to.equal(1)
+ {
+ const body = await commands[1].getAdminList({ filter: 'account' })
+ expect(body.total).to.equal(1)
+ expect(body.data.length).to.equal(1)
- abuseServer2 = res2.body.data[0]
+ abuseServer2 = body.data[0]
- expect(abuseServer2.reason).to.equal('it is a really bad account')
+ expect(abuseServer2.reason).to.equal('it is a really bad account')
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
+ expect(abuseServer2.reporterAccount.name).to.equal('root')
+ expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
+ expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
+ expect(abuseServer2.state.label).to.equal('Pending')
- expect(abuseServer2.moderationComment).to.be.null
+ expect(abuseServer2.moderationComment).to.be.null
+ }
})
it('Should keep the account abuse when deleting the account', async function () {
this.timeout(10000)
- const account = await getAccountFromServer(servers[1].url, 'user_2', servers[1])
- await removeUser(servers[1].url, account.userId, servers[1].accessToken)
+ const account = await getAccountFromServer(servers[1], 'user_2', servers[1])
+ await servers[1].users.remove({ userId: account.userId })
await waitJobs(servers)
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await commands[0].getAdminList({ filter: 'account' })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
- const abuse = (res.body.data as AdminAbuse[]).find(a => a.reason === 'it is a really bad account')
+ const abuse = body.data.find(a => a.reason === 'it is a really bad account')
expect(abuse).to.not.be.undefined
})
it('Should delete the account abuse', async function () {
this.timeout(10000)
- await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
+ await commands[1].delete({ abuseId: abuseServer2.id })
await waitJobs(servers)
{
- const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data.length).to.equal(0)
+ const body = await commands[1].getAdminList({ filter: 'account' })
+ expect(body.total).to.equal(0)
+ expect(body.data.length).to.equal(0)
}
{
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getAdminList({ filter: 'account' })
+ expect(body.total).to.equal(2)
- abuseServer1 = res.body.data[0]
+ abuseServer1 = body.data[0]
}
})
})
describe('Common actions on abuses', function () {
it('Should update the state of an abuse', async function () {
- const body = { state: AbuseState.REJECTED }
- await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
+ await commands[0].update({ abuseId: abuseServer1.id, body: { state: AbuseState.REJECTED } })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, id: abuseServer1.id })
- expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED)
+ const body = await commands[0].getAdminList({ id: abuseServer1.id })
+ expect(body.data[0].state.id).to.equal(AbuseState.REJECTED)
})
it('Should add a moderation comment', async function () {
- const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' }
- await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
+ await commands[0].update({ abuseId: abuseServer1.id, body: { state: AbuseState.ACCEPTED, moderationComment: 'Valid' } })
- const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, id: abuseServer1.id })
- expect(res.body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
- expect(res.body.data[0].moderationComment).to.equal('It is valid')
+ const body = await commands[0].getAdminList({ id: abuseServer1.id })
+ expect(body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
+ expect(body.data[0].moderationComment).to.equal('Valid')
})
})
let userAccessToken: string
before(async function () {
- userAccessToken = await generateUserAccessToken(servers[0], 'user_42')
+ userAccessToken = await servers[0].users.generateUserAndToken('user_42')
- await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: 'user reason 1' })
+ await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: 'user reason 1' })
- const videoId = await getVideoIdFromUUID(servers[0].url, servers[1].video.uuid)
- await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId, reason: 'user reason 2' })
+ const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
+ await commands[0].report({ token: userAccessToken, videoId, reason: 'user reason 2' })
})
it('Should correctly list my abuses', async function () {
{
- const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getUserList({ token: userAccessToken, start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const abuses: UserAbuse[] = res.body.data
+ const abuses = body.data
expect(abuses[0].reason).to.equal('user reason 1')
expect(abuses[1].reason).to.equal('user reason 2')
}
{
- const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 1, count: 1, sort: 'createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getUserList({ token: userAccessToken, start: 1, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const abuses: UserAbuse[] = res.body.data
+ const abuses: UserAbuse[] = body.data
expect(abuses[0].reason).to.equal('user reason 2')
}
{
- const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 1, count: 1, sort: '-createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getUserList({ token: userAccessToken, start: 1, count: 1, sort: '-createdAt' })
+ expect(body.total).to.equal(2)
- const abuses: UserAbuse[] = res.body.data
+ const abuses: UserAbuse[] = body.data
expect(abuses[0].reason).to.equal('user reason 1')
}
})
it('Should correctly filter my abuses by id', async function () {
- const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, id: abuseId1 })
+ const body = await commands[0].getUserList({ token: userAccessToken, id: abuseId1 })
+ expect(body.total).to.equal(1)
- expect(res.body.total).to.equal(1)
-
- const abuses: UserAbuse[] = res.body.data
+ const abuses: UserAbuse[] = body.data
expect(abuses[0].reason).to.equal('user reason 1')
})
it('Should correctly filter my abuses by search', async function () {
- const res = await getUserAbusesList({
- url: servers[0].url,
- token: userAccessToken,
- search: 'server 2'
- })
-
- expect(res.body.total).to.equal(1)
+ const body = await commands[0].getUserList({ token: userAccessToken, search: 'server 2' })
+ expect(body.total).to.equal(1)
- const abuses: UserAbuse[] = res.body.data
+ const abuses: UserAbuse[] = body.data
expect(abuses[0].reason).to.equal('user reason 2')
})
it('Should correctly filter my abuses by state', async function () {
- const body = { state: AbuseState.REJECTED }
- await updateAbuse(servers[0].url, servers[0].accessToken, abuseId1, body)
+ await commands[0].update({ abuseId: abuseId1, body: { state: AbuseState.REJECTED } })
- const res = await getUserAbusesList({
- url: servers[0].url,
- token: userAccessToken,
- state: AbuseState.REJECTED
- })
-
- expect(res.body.total).to.equal(1)
+ const body = await commands[0].getUserList({ token: userAccessToken, state: AbuseState.REJECTED })
+ expect(body.total).to.equal(1)
- const abuses: UserAbuse[] = res.body.data
+ const abuses: UserAbuse[] = body.data
expect(abuses[0].reason).to.equal('user reason 1')
})
})
describe('Abuse messages', async function () {
let abuseId: number
- let userAccessToken: string
+ let userToken: string
let abuseMessageUserId: number
let abuseMessageModerationId: number
before(async function () {
- userAccessToken = await generateUserAccessToken(servers[0], 'user_43')
+ userToken = await servers[0].users.generateUserAndToken('user_43')
- const res = await reportAbuse({
- url: servers[0].url,
- token: userAccessToken,
- videoId: servers[0].video.id,
- reason: 'user 43 reason 1'
- })
-
- abuseId = res.body.abuse.id
+ const body = await commands[0].report({ token: userToken, videoId: servers[0].store.videoCreated.id, reason: 'user 43 reason 1' })
+ abuseId = body.abuse.id
})
it('Should create some messages on the abuse', async function () {
- await addAbuseMessage(servers[0].url, userAccessToken, abuseId, 'message 1')
- await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, 'message 2')
- await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, 'message 3')
- await addAbuseMessage(servers[0].url, userAccessToken, abuseId, 'message 4')
+ await commands[0].addMessage({ token: userToken, abuseId, message: 'message 1' })
+ await commands[0].addMessage({ abuseId, message: 'message 2' })
+ await commands[0].addMessage({ abuseId, message: 'message 3' })
+ await commands[0].addMessage({ token: userToken, abuseId, message: 'message 4' })
})
it('Should have the correct messages count when listing abuses', async function () {
const results = await Promise.all([
- getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, start: 0, count: 50 }),
- getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 0, count: 50 })
+ commands[0].getAdminList({ start: 0, count: 50 }),
+ commands[0].getUserList({ token: userToken, start: 0, count: 50 })
])
- for (const res of results) {
- const abuses: AdminAbuse[] = res.body.data
+ for (const body of results) {
+ const abuses = body.data
const abuse = abuses.find(a => a.id === abuseId)
expect(abuse.countMessages).to.equal(4)
}
it('Should correctly list messages of this abuse', async function () {
const results = await Promise.all([
- listAbuseMessages(servers[0].url, servers[0].accessToken, abuseId),
- listAbuseMessages(servers[0].url, userAccessToken, abuseId)
+ commands[0].listMessages({ abuseId }),
+ commands[0].listMessages({ token: userToken, abuseId })
])
- for (const res of results) {
- expect(res.body.total).to.equal(4)
+ for (const body of results) {
+ expect(body.total).to.equal(4)
- const abuseMessages: AbuseMessage[] = res.body.data
+ const abuseMessages: AbuseMessage[] = body.data
expect(abuseMessages[0].message).to.equal('message 1')
expect(abuseMessages[0].byModerator).to.be.false
})
it('Should delete messages', async function () {
- await deleteAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, abuseMessageModerationId)
- await deleteAbuseMessage(servers[0].url, userAccessToken, abuseId, abuseMessageUserId)
+ await commands[0].deleteMessage({ abuseId, messageId: abuseMessageModerationId })
+ await commands[0].deleteMessage({ token: userToken, abuseId, messageId: abuseMessageUserId })
const results = await Promise.all([
- listAbuseMessages(servers[0].url, servers[0].accessToken, abuseId),
- listAbuseMessages(servers[0].url, userAccessToken, abuseId)
+ commands[0].listMessages({ abuseId }),
+ commands[0].listMessages({ token: userToken, abuseId })
])
- for (const res of results) {
- expect(res.body.total).to.equal(2)
-
- const abuseMessages: AbuseMessage[] = res.body.data
+ for (const body of results) {
+ expect(body.total).to.equal(2)
+ const abuseMessages: AbuseMessage[] = body.data
expect(abuseMessages[0].message).to.equal('message 2')
expect(abuseMessages[1].message).to.equal('message 4')
}
import 'mocha'
import * as chai from 'chai'
-import { getUserNotifications, markAsReadAllNotifications } from '@shared/extra-utils/users/user-notifications'
-import { addUserSubscription, removeUserSubscription } from '@shared/extra-utils/users/user-subscriptions'
-import { UserNotification, UserNotificationType } from '@shared/models'
-import {
- cleanupTests,
- createUser,
- doubleFollow,
- flushAndRunMultipleServers,
- ServerInfo,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils/index'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- addAccountToAccountBlocklist,
- addAccountToServerBlocklist,
- addServerToAccountBlocklist,
- addServerToServerBlocklist,
- removeAccountFromAccountBlocklist,
- removeAccountFromServerBlocklist,
- removeServerFromAccountBlocklist
-} from '../../../../shared/extra-utils/users/blocklist'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
-import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { UserNotificationType } from '@shared/models'
const expect = chai.expect
-async function checkNotifications (url: string, token: string, expected: UserNotificationType[]) {
- const res = await getUserNotifications(url, token, 0, 10, true)
-
- const notifications: UserNotification[] = res.body.data
-
- expect(notifications).to.have.lengthOf(expected.length)
+async function checkNotifications (server: PeerTubeServer, token: string, expected: UserNotificationType[]) {
+ const { data } = await server.notifications.list({ token, start: 0, count: 10, unread: true })
+ expect(data).to.have.lengthOf(expected.length)
for (const type of expected) {
- expect(notifications.find(n => n.type === type)).to.exist
+ expect(data.find(n => n.type === type)).to.exist
}
}
describe('Test blocklist', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoUUID: string
let userToken1: string
async function resetState () {
try {
- await removeUserSubscription(servers[1].url, remoteUserToken, 'user1_channel@' + servers[0].host)
- await removeUserSubscription(servers[1].url, remoteUserToken, 'user2_channel@' + servers[0].host)
+ await servers[1].subscriptions.remove({ token: remoteUserToken, uri: 'user1_channel@' + servers[0].host })
+ await servers[1].subscriptions.remove({ token: remoteUserToken, uri: 'user2_channel@' + servers[0].host })
} catch {}
await waitJobs(servers)
- await markAsReadAllNotifications(servers[0].url, userToken1)
- await markAsReadAllNotifications(servers[0].url, userToken2)
+ await servers[0].notifications.markAsReadAll({ token: userToken1 })
+ await servers[0].notifications.markAsReadAll({ token: userToken2 })
{
- const res = await uploadVideo(servers[0].url, userToken1, { name: 'video' })
- videoUUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video' } })
+ videoUUID = uuid
await waitJobs(servers)
}
{
- await addVideoCommentThread(servers[1].url, remoteUserToken, videoUUID, '@user2@' + servers[0].host + ' hello')
+ await servers[1].comments.createThread({
+ token: remoteUserToken,
+ videoId: videoUUID,
+ text: '@user2@' + servers[0].host + ' hello'
+ })
}
{
- await addUserSubscription(servers[1].url, remoteUserToken, 'user1_channel@' + servers[0].host)
- await addUserSubscription(servers[1].url, remoteUserToken, 'user2_channel@' + servers[0].host)
+ await servers[1].subscriptions.add({ token: remoteUserToken, targetUri: 'user1_channel@' + servers[0].host })
+ await servers[1].subscriptions.add({ token: remoteUserToken, targetUri: 'user2_channel@' + servers[0].host })
}
await waitJobs(servers)
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
{
const user = { username: 'user1', password: 'password' }
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].users.create({
username: user.username,
password: user.password,
videoQuota: -1,
videoQuotaDaily: -1
})
- userToken1 = await userLogin(servers[0], user)
- await uploadVideo(servers[0].url, userToken1, { name: 'video user 1' })
+ userToken1 = await servers[0].login.getAccessToken(user)
+ await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video user 1' } })
}
{
const user = { username: 'user2', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- userToken2 = await userLogin(servers[0], user)
+ userToken2 = await servers[0].login.getAccessToken(user)
}
{
const user = { username: 'user3', password: 'password' }
- await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
+ await servers[1].users.create({ username: user.username, password: user.password })
- remoteUserToken = await userLogin(servers[1], user)
+ remoteUserToken = await servers[1].login.getAccessToken(user)
}
await doubleFollow(servers[0], servers[1])
it('Should have appropriate notifications', async function () {
const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken1, notifs)
+ await checkNotifications(servers[0], userToken1, notifs)
})
it('Should block an account', async function () {
this.timeout(10000)
- await addAccountToAccountBlocklist(servers[0].url, userToken1, 'user3@' + servers[1].host)
+ await servers[0].blocklist.addToMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host })
await waitJobs(servers)
})
it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0].url, userToken1, [])
+ await checkNotifications(servers[0], userToken1, [])
})
it('Should have notifications of this account on user 2', async function () {
const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken2, notifs)
+ await checkNotifications(servers[0], userToken2, notifs)
- await removeAccountFromAccountBlocklist(servers[0].url, userToken1, 'user3@' + servers[1].host)
+ await servers[0].blocklist.removeFromMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host })
})
})
it('Should have appropriate notifications', async function () {
const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken1, notifs)
+ await checkNotifications(servers[0], userToken1, notifs)
})
it('Should block an account', async function () {
this.timeout(10000)
- await addServerToAccountBlocklist(servers[0].url, userToken1, servers[1].host)
+ await servers[0].blocklist.addToMyBlocklist({ token: userToken1, server: servers[1].host })
await waitJobs(servers)
})
it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0].url, userToken1, [])
+ await checkNotifications(servers[0], userToken1, [])
})
it('Should have notifications of this account on user 2', async function () {
const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken2, notifs)
+ await checkNotifications(servers[0], userToken2, notifs)
- await removeServerFromAccountBlocklist(servers[0].url, userToken1, servers[1].host)
+ await servers[0].blocklist.removeFromMyBlocklist({ token: userToken1, server: servers[1].host })
})
})
it('Should have appropriate notifications', async function () {
{
const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken1, notifs)
+ await checkNotifications(servers[0], userToken1, notifs)
}
{
const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken2, notifs)
+ await checkNotifications(servers[0], userToken2, notifs)
}
})
it('Should block an account', async function () {
this.timeout(10000)
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'user3@' + servers[1].host)
+ await servers[0].blocklist.addToServerBlocklist({ account: 'user3@' + servers[1].host })
await waitJobs(servers)
})
it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0].url, userToken1, [])
- await checkNotifications(servers[0].url, userToken2, [])
+ await checkNotifications(servers[0], userToken1, [])
+ await checkNotifications(servers[0], userToken2, [])
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'user3@' + servers[1].host)
+ await servers[0].blocklist.removeFromServerBlocklist({ account: 'user3@' + servers[1].host })
})
})
it('Should have appropriate notifications', async function () {
{
const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken1, notifs)
+ await checkNotifications(servers[0], userToken1, notifs)
}
{
const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0].url, userToken2, notifs)
+ await checkNotifications(servers[0], userToken2, notifs)
}
})
it('Should block an account', async function () {
this.timeout(10000)
- await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
+ await servers[0].blocklist.addToServerBlocklist({ server: servers[1].host })
await waitJobs(servers)
})
it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0].url, userToken1, [])
- await checkNotifications(servers[0].url, userToken2, [])
+ await checkNotifications(servers[0], userToken1, [])
+ await checkNotifications(servers[0], userToken2, [])
})
})
import 'mocha'
import * as chai from 'chai'
import {
- addAccountToAccountBlocklist,
- addAccountToServerBlocklist,
- addServerToAccountBlocklist,
- addServerToServerBlocklist,
- addVideoCommentReply,
- addVideoCommentThread,
+ BlocklistCommand,
cleanupTests,
- createUser,
- deleteVideoComment,
+ CommentsCommand,
+ createMultipleServers,
doubleFollow,
- findCommentId,
- flushAndRunMultipleServers,
- follow,
- getAccountBlocklistByAccount,
- getAccountBlocklistByServer,
- getServerBlocklistByAccount,
- getServerBlocklistByServer,
- getUserNotifications,
- getVideoCommentThreads,
- getVideosList,
- getVideosListWithToken,
- getVideoThreadComments,
- removeAccountFromAccountBlocklist,
- removeAccountFromServerBlocklist,
- removeServerFromAccountBlocklist,
- removeServerFromServerBlocklist,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- unfollow,
- uploadVideo,
- userLogin,
waitJobs
} from '@shared/extra-utils'
-import {
- AccountBlock,
- ServerBlock,
- UserNotification,
- UserNotificationType,
- Video,
- VideoComment,
- VideoCommentThreadTree
-} from '@shared/models'
+import { UserNotificationType } from '@shared/models'
const expect = chai.expect
-async function checkAllVideos (url: string, token: string) {
+async function checkAllVideos (server: PeerTubeServer, token: string) {
{
- const res = await getVideosListWithToken(url, token)
-
- expect(res.body.data).to.have.lengthOf(5)
+ const { data } = await server.videos.listWithToken({ token })
+ expect(data).to.have.lengthOf(5)
}
{
- const res = await getVideosList(url)
-
- expect(res.body.data).to.have.lengthOf(5)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(5)
}
}
-async function checkAllComments (url: string, token: string, videoUUID: string) {
- const resThreads = await getVideoCommentThreads(url, videoUUID, 0, 25, '-createdAt', token)
+async function checkAllComments (server: PeerTubeServer, token: string, videoUUID: string) {
+ const { data } = await server.comments.listThreads({ videoId: videoUUID, start: 0, count: 25, sort: '-createdAt', token })
- const allThreads: VideoComment[] = resThreads.body.data
- const threads = allThreads.filter(t => t.isDeleted === false)
+ const threads = data.filter(t => t.isDeleted === false)
expect(threads).to.have.lengthOf(2)
for (const thread of threads) {
- const res = await getVideoThreadComments(url, videoUUID, thread.id, token)
-
- const tree: VideoCommentThreadTree = res.body
+ const tree = await server.comments.getThread({ videoId: videoUUID, threadId: thread.id, token })
expect(tree.children).to.have.lengthOf(1)
}
}
async function checkCommentNotification (
- mainServer: ServerInfo,
- comment: { server: ServerInfo, token: string, videoUUID: string, text: string },
+ mainServer: PeerTubeServer,
+ comment: { server: PeerTubeServer, token: string, videoUUID: string, text: string },
check: 'presence' | 'absence'
) {
- const resComment = await addVideoCommentThread(comment.server.url, comment.token, comment.videoUUID, comment.text)
- const created = resComment.body.comment as VideoComment
- const threadId = created.id
- const createdAt = created.createdAt
+ const command = comment.server.comments
+
+ const { threadId, createdAt } = await command.createThread({ token: comment.token, videoId: comment.videoUUID, text: comment.text })
await waitJobs([ mainServer, comment.server ])
- const res = await getUserNotifications(mainServer.url, mainServer.accessToken, 0, 30)
- const commentNotifications = (res.body.data as UserNotification[])
- .filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
+ const { data } = await mainServer.notifications.list({ start: 0, count: 30 })
+ const commentNotifications = data.filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
if (check === 'presence') expect(commentNotifications).to.have.lengthOf(1)
else expect(commentNotifications).to.have.lengthOf(0)
- await deleteVideoComment(comment.server.url, comment.token, comment.videoUUID, threadId)
+ await command.delete({ token: comment.token, videoId: comment.videoUUID, commentId: threadId })
await waitJobs([ mainServer, comment.server ])
}
describe('Test blocklist', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoUUID1: string
let videoUUID2: string
let videoUUID3: string
let userModeratorToken: string
let userToken2: string
+ let command: BlocklistCommand
+ let commentsCommand: CommentsCommand[]
+
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
await setAccessTokensToServers(servers)
+ command = servers[0].blocklist
+ commentsCommand = servers.map(s => s.comments)
+
{
const user = { username: 'user1', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- userToken1 = await userLogin(servers[0], user)
- await uploadVideo(servers[0].url, userToken1, { name: 'video user 1' })
+ userToken1 = await servers[0].login.getAccessToken(user)
+ await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video user 1' } })
}
{
const user = { username: 'moderator', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- userModeratorToken = await userLogin(servers[0], user)
+ userModeratorToken = await servers[0].login.getAccessToken(user)
}
{
const user = { username: 'user2', password: 'password' }
- await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
+ await servers[1].users.create({ username: user.username, password: user.password })
- userToken2 = await userLogin(servers[1], user)
- await uploadVideo(servers[1].url, userToken2, { name: 'video user 2' })
+ userToken2 = await servers[1].login.getAccessToken(user)
+ await servers[1].videos.upload({ token: userToken2, attributes: { name: 'video user 2' } })
}
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video server 1' })
- videoUUID1 = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video server 1' } })
+ videoUUID1 = uuid
}
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video server 2' })
- videoUUID2 = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video server 2' } })
+ videoUUID2 = uuid
}
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 2 server 1' })
- videoUUID3 = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 2 server 1' } })
+ videoUUID3 = uuid
}
await doubleFollow(servers[0], servers[1])
await doubleFollow(servers[0], servers[2])
{
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID1, 'comment root 1')
- const resReply = await addVideoCommentReply(servers[0].url, userToken1, videoUUID1, resComment.body.comment.id, 'comment user 1')
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID1, resReply.body.comment.id, 'comment root 1')
+ const created = await commentsCommand[0].createThread({ videoId: videoUUID1, text: 'comment root 1' })
+ const reply = await commentsCommand[0].addReply({
+ token: userToken1,
+ videoId: videoUUID1,
+ toCommentId: created.id,
+ text: 'comment user 1'
+ })
+ await commentsCommand[0].addReply({ videoId: videoUUID1, toCommentId: reply.id, text: 'comment root 1' })
}
{
- const resComment = await addVideoCommentThread(servers[0].url, userToken1, videoUUID1, 'comment user 1')
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID1, resComment.body.comment.id, 'comment root 1')
+ const created = await commentsCommand[0].createThread({ token: userToken1, videoId: videoUUID1, text: 'comment user 1' })
+ await commentsCommand[0].addReply({ videoId: videoUUID1, toCommentId: created.id, text: 'comment root 1' })
}
await waitJobs(servers)
describe('When managing account blocklist', function () {
it('Should list all videos', function () {
- return checkAllVideos(servers[0].url, servers[0].accessToken)
+ return checkAllVideos(servers[0], servers[0].accessToken)
})
it('Should list the comments', function () {
- return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
})
it('Should block a remote account', async function () {
- await addAccountToAccountBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
+ await command.addToMyBlocklist({ account: 'user2@localhost:' + servers[1].port })
})
it('Should hide its videos', async function () {
- const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
+ const { data } = await servers[0].videos.listWithToken()
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(4)
+ expect(data).to.have.lengthOf(4)
- const v = videos.find(v => v.name === 'video user 2')
+ const v = data.find(v => v.name === 'video user 2')
expect(v).to.be.undefined
})
it('Should block a local account', async function () {
- await addAccountToAccountBlocklist(servers[0].url, servers[0].accessToken, 'user1')
+ await command.addToMyBlocklist({ account: 'user1' })
})
it('Should hide its videos', async function () {
- const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
+ const { data } = await servers[0].videos.listWithToken()
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(3)
+ expect(data).to.have.lengthOf(3)
- const v = videos.find(v => v.name === 'video user 1')
+ const v = data.find(v => v.name === 'video user 1')
expect(v).to.be.undefined
})
it('Should hide its comments', async function () {
- const resThreads = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 25, '-createdAt', servers[0].accessToken)
-
- const threads: VideoComment[] = resThreads.body.data
- expect(threads).to.have.lengthOf(1)
- expect(threads[0].totalReplies).to.equal(1)
-
- const t = threads.find(t => t.text === 'comment user 1')
+ const { data } = await commentsCommand[0].listThreads({
+ token: servers[0].accessToken,
+ videoId: videoUUID1,
+ start: 0,
+ count: 25,
+ sort: '-createdAt'
+ })
+
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].totalReplies).to.equal(1)
+
+ const t = data.find(t => t.text === 'comment user 1')
expect(t).to.be.undefined
- for (const thread of threads) {
- const res = await getVideoThreadComments(servers[0].url, videoUUID1, thread.id, servers[0].accessToken)
-
- const tree: VideoCommentThreadTree = res.body
+ for (const thread of data) {
+ const tree = await commentsCommand[0].getThread({
+ videoId: videoUUID1,
+ threadId: thread.id,
+ token: servers[0].accessToken
+ })
expect(tree.children).to.have.lengthOf(0)
}
})
})
it('Should list all the videos with another user', async function () {
- return checkAllVideos(servers[0].url, userToken1)
+ return checkAllVideos(servers[0], userToken1)
})
it('Should list blocked accounts', async function () {
{
- const res = await getAccountBlocklistByAccount(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
- const blocks: AccountBlock[] = res.body.data
+ const body = await command.listMyAccountBlocklist({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- expect(res.body.total).to.equal(2)
-
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('root')
expect(block.byAccount.name).to.equal('root')
expect(block.blockedAccount.displayName).to.equal('user2')
}
{
- const res = await getAccountBlocklistByAccount(servers[0].url, servers[0].accessToken, 1, 2, 'createdAt')
- const blocks: AccountBlock[] = res.body.data
-
- expect(res.body.total).to.equal(2)
+ const body = await command.listMyAccountBlocklist({ start: 1, count: 2, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('root')
expect(block.byAccount.name).to.equal('root')
expect(block.blockedAccount.displayName).to.equal('user1')
this.timeout(60000)
{
- await addVideoCommentThread(servers[1].url, userToken2, videoUUID3, 'comment user 2')
+ await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID3, text: 'comment user 2' })
await waitJobs(servers)
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID3, 'uploader')
+ await commentsCommand[0].createThread({ token: servers[0].accessToken, videoId: videoUUID3, text: 'uploader' })
await waitJobs(servers)
- const commentId = await findCommentId(servers[1].url, videoUUID3, 'uploader')
+ const commentId = await commentsCommand[1].findCommentId({ videoId: videoUUID3, text: 'uploader' })
const message = 'reply by user 2'
- const resReply = await addVideoCommentReply(servers[1].url, userToken2, videoUUID3, commentId, message)
- await addVideoCommentReply(servers[1].url, servers[1].accessToken, videoUUID3, resReply.body.comment.id, 'another reply')
+ const reply = await commentsCommand[1].addReply({ token: userToken2, videoId: videoUUID3, toCommentId: commentId, text: message })
+ await commentsCommand[1].addReply({ videoId: videoUUID3, toCommentId: reply.id, text: 'another reply' })
await waitJobs(servers)
}
// Server 2 has all the comments
{
- const resThreads = await getVideoCommentThreads(servers[1].url, videoUUID3, 0, 25, '-createdAt')
- const threads: VideoComment[] = resThreads.body.data
-
- expect(threads).to.have.lengthOf(2)
- expect(threads[0].text).to.equal('uploader')
- expect(threads[1].text).to.equal('comment user 2')
+ const { data } = await commentsCommand[1].listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
- const resReplies = await getVideoThreadComments(servers[1].url, videoUUID3, threads[0].id)
+ expect(data).to.have.lengthOf(2)
+ expect(data[0].text).to.equal('uploader')
+ expect(data[1].text).to.equal('comment user 2')
- const tree: VideoCommentThreadTree = resReplies.body
+ const tree = await commentsCommand[1].getThread({ videoId: videoUUID3, threadId: data[0].id })
expect(tree.children).to.have.lengthOf(1)
expect(tree.children[0].comment.text).to.equal('reply by user 2')
expect(tree.children[0].children).to.have.lengthOf(1)
// Server 1 and 3 should only have uploader comments
for (const server of [ servers[0], servers[2] ]) {
- const resThreads = await getVideoCommentThreads(server.url, videoUUID3, 0, 25, '-createdAt')
- const threads: VideoComment[] = resThreads.body.data
+ const { data } = await server.comments.listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
- expect(threads).to.have.lengthOf(1)
- expect(threads[0].text).to.equal('uploader')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].text).to.equal('uploader')
- const resReplies = await getVideoThreadComments(server.url, videoUUID3, threads[0].id)
+ const tree = await server.comments.getThread({ videoId: videoUUID3, threadId: data[0].id })
- const tree: VideoCommentThreadTree = resReplies.body
- if (server.serverNumber === 1) {
- expect(tree.children).to.have.lengthOf(0)
- } else {
- expect(tree.children).to.have.lengthOf(1)
- }
+ if (server.serverNumber === 1) expect(tree.children).to.have.lengthOf(0)
+ else expect(tree.children).to.have.lengthOf(1)
}
})
it('Should unblock the remote account', async function () {
- await removeAccountFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
+ await command.removeFromMyBlocklist({ account: 'user2@localhost:' + servers[1].port })
})
it('Should display its videos', async function () {
- const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
-
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(4)
+ const { data } = await servers[0].videos.listWithToken()
+ expect(data).to.have.lengthOf(4)
- const v = videos.find(v => v.name === 'video user 2')
+ const v = data.find(v => v.name === 'video user 2')
expect(v).not.to.be.undefined
})
it('Should display its comments on my video', async function () {
for (const server of servers) {
- const resThreads = await getVideoCommentThreads(server.url, videoUUID3, 0, 25, '-createdAt')
- const threads: VideoComment[] = resThreads.body.data
+ const { data } = await server.comments.listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
// Server 3 should not have 2 comment threads, because server 1 did not forward the server 2 comment
if (server.serverNumber === 3) {
- expect(threads).to.have.lengthOf(1)
+ expect(data).to.have.lengthOf(1)
continue
}
- expect(threads).to.have.lengthOf(2)
- expect(threads[0].text).to.equal('uploader')
- expect(threads[1].text).to.equal('comment user 2')
+ expect(data).to.have.lengthOf(2)
+ expect(data[0].text).to.equal('uploader')
+ expect(data[1].text).to.equal('comment user 2')
- const resReplies = await getVideoThreadComments(server.url, videoUUID3, threads[0].id)
-
- const tree: VideoCommentThreadTree = resReplies.body
+ const tree = await server.comments.getThread({ videoId: videoUUID3, threadId: data[0].id })
expect(tree.children).to.have.lengthOf(1)
expect(tree.children[0].comment.text).to.equal('reply by user 2')
expect(tree.children[0].children).to.have.lengthOf(1)
})
it('Should unblock the local account', async function () {
- await removeAccountFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'user1')
+ await command.removeFromMyBlocklist({ account: 'user1' })
})
it('Should display its comments', function () {
- return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
})
it('Should have a notification from a non blocked account', async function () {
})
describe('When managing server blocklist', function () {
+
it('Should list all videos', function () {
- return checkAllVideos(servers[0].url, servers[0].accessToken)
+ return checkAllVideos(servers[0], servers[0].accessToken)
})
it('Should list the comments', function () {
- return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
})
it('Should block a remote server', async function () {
- await addServerToAccountBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.addToMyBlocklist({ server: 'localhost:' + servers[1].port })
})
it('Should hide its videos', async function () {
- const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
+ const { data } = await servers[0].videos.listWithToken()
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(3)
+ expect(data).to.have.lengthOf(3)
- const v1 = videos.find(v => v.name === 'video user 2')
- const v2 = videos.find(v => v.name === 'video server 2')
+ const v1 = data.find(v => v.name === 'video user 2')
+ const v2 = data.find(v => v.name === 'video server 2')
expect(v1).to.be.undefined
expect(v2).to.be.undefined
})
it('Should list all the videos with another user', async function () {
- return checkAllVideos(servers[0].url, userToken1)
+ return checkAllVideos(servers[0], userToken1)
})
it('Should hide its comments', async function () {
this.timeout(10000)
- const resThreads = await addVideoCommentThread(servers[1].url, userToken2, videoUUID1, 'hidden comment 2')
- const threadId = resThreads.body.comment.id
+ const { id } = await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID1, text: 'hidden comment 2' })
await waitJobs(servers)
- await checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ await checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- await deleteVideoComment(servers[1].url, userToken2, videoUUID1, threadId)
+ await commentsCommand[1].delete({ token: userToken2, videoId: videoUUID1, commentId: id })
})
it('Should not have notifications from blocked server', async function () {
})
it('Should list blocked servers', async function () {
- const res = await getServerBlocklistByAccount(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
- const blocks: ServerBlock[] = res.body.data
-
- expect(res.body.total).to.equal(1)
+ const body = await command.listMyServerBlocklist({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('root')
expect(block.byAccount.name).to.equal('root')
expect(block.blockedServer.host).to.equal('localhost:' + servers[1].port)
})
it('Should unblock the remote server', async function () {
- await removeServerFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.removeFromMyBlocklist({ server: 'localhost:' + servers[1].port })
})
it('Should display its videos', function () {
- return checkAllVideos(servers[0].url, servers[0].accessToken)
+ return checkAllVideos(servers[0], servers[0].accessToken)
})
it('Should display its comments', function () {
- return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
})
it('Should have notification from unblocked server', async function () {
describe('When managing account blocklist', function () {
it('Should list all videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0].url, token)
+ await checkAllVideos(servers[0], token)
}
})
it('Should list the comments', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0].url, token, videoUUID1)
+ await checkAllComments(servers[0], token, videoUUID1)
}
})
it('Should block a remote account', async function () {
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
+ await command.addToServerBlocklist({ account: 'user2@localhost:' + servers[1].port })
})
it('Should hide its videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const res = await getVideosListWithToken(servers[0].url, token)
+ const { data } = await servers[0].videos.listWithToken({ token })
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(4)
+ expect(data).to.have.lengthOf(4)
- const v = videos.find(v => v.name === 'video user 2')
+ const v = data.find(v => v.name === 'video user 2')
expect(v).to.be.undefined
}
})
it('Should block a local account', async function () {
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'user1')
+ await command.addToServerBlocklist({ account: 'user1' })
})
it('Should hide its videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const res = await getVideosListWithToken(servers[0].url, token)
+ const { data } = await servers[0].videos.listWithToken({ token })
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(3)
+ expect(data).to.have.lengthOf(3)
- const v = videos.find(v => v.name === 'video user 1')
+ const v = data.find(v => v.name === 'video user 1')
expect(v).to.be.undefined
}
})
it('Should hide its comments', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const resThreads = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 20, '-createdAt', token)
-
- let threads: VideoComment[] = resThreads.body.data
- threads = threads.filter(t => t.isDeleted === false)
+ const { data } = await commentsCommand[0].listThreads({ videoId: videoUUID1, count: 20, sort: '-createdAt', token })
+ const threads = data.filter(t => t.isDeleted === false)
expect(threads).to.have.lengthOf(1)
expect(threads[0].totalReplies).to.equal(1)
expect(t).to.be.undefined
for (const thread of threads) {
- const res = await getVideoThreadComments(servers[0].url, videoUUID1, thread.id, token)
-
- const tree: VideoCommentThreadTree = res.body
+ const tree = await commentsCommand[0].getThread({ videoId: videoUUID1, threadId: thread.id, token })
expect(tree.children).to.have.lengthOf(0)
}
}
it('Should list blocked accounts', async function () {
{
- const res = await getAccountBlocklistByServer(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
- const blocks: AccountBlock[] = res.body.data
-
- expect(res.body.total).to.equal(2)
+ const body = await command.listServerAccountBlocklist({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('peertube')
expect(block.byAccount.name).to.equal('peertube')
expect(block.blockedAccount.displayName).to.equal('user2')
}
{
- const res = await getAccountBlocklistByServer(servers[0].url, servers[0].accessToken, 1, 2, 'createdAt')
- const blocks: AccountBlock[] = res.body.data
+ const body = await command.listServerAccountBlocklist({ start: 1, count: 2, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- expect(res.body.total).to.equal(2)
-
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('peertube')
expect(block.byAccount.name).to.equal('peertube')
expect(block.blockedAccount.displayName).to.equal('user1')
})
it('Should unblock the remote account', async function () {
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
+ await command.removeFromServerBlocklist({ account: 'user2@localhost:' + servers[1].port })
})
it('Should display its videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const res = await getVideosListWithToken(servers[0].url, token)
-
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(4)
+ const { data } = await servers[0].videos.listWithToken({ token })
+ expect(data).to.have.lengthOf(4)
- const v = videos.find(v => v.name === 'video user 2')
+ const v = data.find(v => v.name === 'video user 2')
expect(v).not.to.be.undefined
}
})
it('Should unblock the local account', async function () {
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'user1')
+ await command.removeFromServerBlocklist({ account: 'user1' })
})
it('Should display its comments', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0].url, token, videoUUID1)
+ await checkAllComments(servers[0], token, videoUUID1)
}
})
describe('When managing server blocklist', function () {
it('Should list all videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0].url, token)
+ await checkAllVideos(servers[0], token)
}
})
it('Should list the comments', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0].url, token, videoUUID1)
+ await checkAllComments(servers[0], token, videoUUID1)
}
})
it('Should block a remote server', async function () {
- await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.addToServerBlocklist({ server: 'localhost:' + servers[1].port })
})
it('Should hide its videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const res1 = await getVideosList(servers[0].url)
- const res2 = await getVideosListWithToken(servers[0].url, token)
+ const requests = [
+ servers[0].videos.list(),
+ servers[0].videos.listWithToken({ token })
+ ]
- for (const res of [ res1, res2 ]) {
- const videos: Video[] = res.body.data
- expect(videos).to.have.lengthOf(3)
+ for (const req of requests) {
+ const { data } = await req
+ expect(data).to.have.lengthOf(3)
- const v1 = videos.find(v => v.name === 'video user 2')
- const v2 = videos.find(v => v.name === 'video server 2')
+ const v1 = data.find(v => v.name === 'video user 2')
+ const v2 = data.find(v => v.name === 'video server 2')
expect(v1).to.be.undefined
expect(v2).to.be.undefined
it('Should hide its comments', async function () {
this.timeout(10000)
- const resThreads = await addVideoCommentThread(servers[1].url, userToken2, videoUUID1, 'hidden comment 2')
- const threadId = resThreads.body.comment.id
+ const { id } = await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID1, text: 'hidden comment 2' })
await waitJobs(servers)
- await checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
+ await checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- await deleteVideoComment(servers[1].url, userToken2, videoUUID1, threadId)
+ await commentsCommand[1].delete({ token: userToken2, videoId: videoUUID1, commentId: id })
})
it('Should not have notification from blocked instances by instance', async function () {
{
const now = new Date()
- await unfollow(servers[1].url, servers[1].accessToken, servers[0])
+ await servers[1].follows.unfollow({ target: servers[0] })
await waitJobs(servers)
- await follow(servers[1].url, [ servers[0].host ], servers[1].accessToken)
+ await servers[1].follows.follow({ hosts: [ servers[0].host ] })
await waitJobs(servers)
- const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30)
- const commentNotifications = (res.body.data as UserNotification[])
- .filter(n => {
- return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER &&
- n.createdAt >= now.toISOString()
- })
+ const { data } = await servers[0].notifications.list({ start: 0, count: 30 })
+ const commentNotifications = data.filter(n => {
+ return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
+ })
expect(commentNotifications).to.have.lengthOf(0)
}
})
it('Should list blocked servers', async function () {
- const res = await getServerBlocklistByServer(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
- const blocks: ServerBlock[] = res.body.data
-
- expect(res.body.total).to.equal(1)
+ const body = await command.listServerServerBlocklist({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
- const block = blocks[0]
+ const block = body.data[0]
expect(block.byAccount.displayName).to.equal('peertube')
expect(block.byAccount.name).to.equal('peertube')
expect(block.blockedServer.host).to.equal('localhost:' + servers[1].port)
})
it('Should unblock the remote server', async function () {
- await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.removeFromServerBlocklist({ server: 'localhost:' + servers[1].port })
})
it('Should list all videos', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0].url, token)
+ await checkAllVideos(servers[0], token)
}
})
it('Should list the comments', async function () {
for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0].url, token, videoUUID1)
+ await checkAllComments(servers[0], token, videoUUID1)
}
})
{
const now = new Date()
- await unfollow(servers[1].url, servers[1].accessToken, servers[0])
+ await servers[1].follows.unfollow({ target: servers[0] })
await waitJobs(servers)
- await follow(servers[1].url, [ servers[0].host ], servers[1].accessToken)
+ await servers[1].follows.follow({ hosts: [ servers[0].host ] })
await waitJobs(servers)
- const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30)
- const commentNotifications = (res.body.data as UserNotification[])
- .filter(n => {
- return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER &&
- n.createdAt >= now.toISOString()
- })
+ const { data } = await servers[0].notifications.list({ start: 0, count: 30 })
+ const commentNotifications = data.filter(n => {
+ return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
+ })
expect(commentNotifications).to.have.lengthOf(1)
}
import * as chai from 'chai'
import { orderBy } from 'lodash'
import {
- addVideoToBlacklist,
+ BlacklistCommand,
cleanupTests,
- createUser,
- flushAndRunMultipleServers,
- getBlacklistedVideosList,
- getMyUserInformation,
- getMyVideos,
- getVideosList,
+ createMultipleServers,
+ doubleFollow,
+ FIXTURE_URLS,
killallServers,
- removeVideoFromBlacklist,
- reRunServer,
- searchVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateVideo,
- updateVideoBlacklist,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils/index'
-import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { getGoodVideoUrl, getMagnetURI, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
-import { User, UserRole } from '../../../../shared/models/users'
-import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
-import { VideoBlacklist, VideoBlacklistType } from '../../../../shared/models/videos'
+ waitJobs
+} from '@shared/extra-utils'
+import { UserAdminFlag, UserRole, VideoBlacklist, VideoBlacklistType } from '@shared/models'
const expect = chai.expect
describe('Test video blacklist', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoId: number
+ let command: BlacklistCommand
- async function blacklistVideosOnServer (server: ServerInfo) {
- const res = await getVideosList(server.url)
+ async function blacklistVideosOnServer (server: PeerTubeServer) {
+ const { data } = await server.videos.list()
- const videos = res.body.data
- for (const video of videos) {
- await addVideoToBlacklist(server.url, server.accessToken, video.id, 'super reason')
+ for (const video of data) {
+ await server.blacklist.add({ videoId: video.id, reason: 'super reason' })
}
}
this.timeout(50000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
// Upload 2 videos on server 2
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on server 2' })
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on server 2' })
+ await servers[1].videos.upload({ attributes: { name: 'My 1st video', description: 'A video on server 2' } })
+ await servers[1].videos.upload({ attributes: { name: 'My 2nd video', description: 'A video on server 2' } })
// Wait videos propagation, server 2 has transcoding enabled
await waitJobs(servers)
+ command = servers[0].blacklist
+
// Blacklist the two videos on server 1
await blacklistVideosOnServer(servers[0])
})
it('Should not have the video blacklisted in videos list/search on server 1', async function () {
{
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(total).to.equal(0)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(0)
}
{
- const res = await searchVideo(servers[0].url, 'name')
+ const body = await servers[0].search.searchVideos({ search: 'video' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
}
})
it('Should have the blacklisted video in videos list/search on server 2', async function () {
{
- const res = await getVideosList(servers[1].url)
+ const { total, data } = await servers[1].videos.list()
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(2)
+ expect(total).to.equal(2)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(2)
}
{
- const res = await searchVideo(servers[1].url, 'video')
+ const body = await servers[1].search.searchVideos({ search: 'video' })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(2)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(2)
}
})
})
describe('When listing manually blacklisted videos', function () {
it('Should display all the blacklisted videos', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken })
-
- expect(res.body.total).to.equal(2)
+ const body = await command.list()
+ expect(body.total).to.equal(2)
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(2)
})
it('Should display all the blacklisted videos when applying manual type filter', async function () {
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- type: VideoBlacklistType.MANUAL
- })
+ const body = await command.list({ type: VideoBlacklistType.MANUAL })
+ expect(body.total).to.equal(2)
- expect(res.body.total).to.equal(2)
-
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(2)
})
it('Should display nothing when applying automatic type filter', async function () {
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
- })
-
- expect(res.body.total).to.equal(0)
+ const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
+ expect(body.total).to.equal(0)
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(0)
})
it('Should get the correct sort when sorting by descending id', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: '-id' })
- expect(res.body.total).to.equal(2)
+ const body = await command.list({ sort: '-id' })
+ expect(body.total).to.equal(2)
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(2)
- const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ])
-
+ const result = orderBy(body.data, [ 'id' ], [ 'desc' ])
expect(blacklistedVideos).to.deep.equal(result)
})
it('Should get the correct sort when sorting by descending video name', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: '-name' })
- expect(res.body.total).to.equal(2)
+ const body = await command.list({ sort: '-name' })
+ expect(body.total).to.equal(2)
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(2)
- const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ])
-
+ const result = orderBy(body.data, [ 'name' ], [ 'desc' ])
expect(blacklistedVideos).to.deep.equal(result)
})
it('Should get the correct sort when sorting by ascending creation date', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await command.list({ sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const blacklistedVideos = res.body.data
+ const blacklistedVideos = body.data
expect(blacklistedVideos).to.be.an('array')
expect(blacklistedVideos.length).to.equal(2)
- const result = orderBy(res.body.data, [ 'createdAt' ])
-
+ const result = orderBy(body.data, [ 'createdAt' ])
expect(blacklistedVideos).to.deep.equal(result)
})
})
describe('When updating blacklisted videos', function () {
it('Should change the reason', async function () {
- await updateVideoBlacklist(servers[0].url, servers[0].accessToken, videoId, 'my super reason updated')
+ await command.update({ videoId, reason: 'my super reason updated' })
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: '-name' })
- const video = res.body.data.find(b => b.video.id === videoId)
+ const body = await command.list({ sort: '-name' })
+ const video = body.data.find(b => b.video.id === videoId)
expect(video.reason).to.equal('my super reason updated')
})
it('Should display blacklisted videos', async function () {
await blacklistVideosOnServer(servers[1])
- const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 5)
+ const { total, data } = await servers[1].videos.listMyVideos()
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(total).to.equal(2)
+ expect(data).to.have.lengthOf(2)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.blacklisted).to.be.true
expect(video.blacklistedReason).to.equal('super reason')
}
let blacklist = []
it('Should not have any video in videos list on server 1', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(0)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(0)
})
it('Should remove a video from the blacklist on server 1', async function () {
// Get one video in the blacklist
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: '-name' })
- videoToRemove = res.body.data[0]
- blacklist = res.body.data.slice(1)
+ const body = await command.list({ sort: '-name' })
+ videoToRemove = body.data[0]
+ blacklist = body.data.slice(1)
// Remove it
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoToRemove.video.id)
+ await command.remove({ videoId: videoToRemove.video.id })
})
it('Should have the ex-blacklisted video in videos list on server 1', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(1)
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(1)
- expect(videos[0].name).to.equal(videoToRemove.video.name)
- expect(videos[0].id).to.equal(videoToRemove.video.id)
+ expect(data[0].name).to.equal(videoToRemove.video.name)
+ expect(data[0].id).to.equal(videoToRemove.video.id)
})
it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: '-name' })
- expect(res.body.total).to.equal(1)
+ const body = await command.list({ sort: '-name' })
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos.length).to.equal(1)
expect(videos).to.deep.equal(blacklist)
this.timeout(10000)
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'Video 3' })
- video3UUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'Video 3' } })
+ video3UUID = uuid
}
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'Video 4' })
- video4UUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'Video 4' } })
+ video4UUID = uuid
}
await waitJobs(servers)
it('Should blacklist video 3 and keep it federated', async function () {
this.timeout(10000)
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, video3UUID, 'super reason', false)
+ await command.add({ videoId: video3UUID, reason: 'super reason', unfederate: false })
await waitJobs(servers)
{
- const res = await getVideosList(servers[0].url)
- expect(res.body.data.find(v => v.uuid === video3UUID)).to.be.undefined
+ const { data } = await servers[0].videos.list()
+ expect(data.find(v => v.uuid === video3UUID)).to.be.undefined
}
{
- const res = await getVideosList(servers[1].url)
- expect(res.body.data.find(v => v.uuid === video3UUID)).to.not.be.undefined
+ const { data } = await servers[1].videos.list()
+ expect(data.find(v => v.uuid === video3UUID)).to.not.be.undefined
}
})
it('Should unfederate the video', async function () {
this.timeout(10000)
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, video4UUID, 'super reason', true)
+ await command.add({ videoId: video4UUID, reason: 'super reason', unfederate: true })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined
+ const { data } = await server.videos.list()
+ expect(data.find(v => v.uuid === video4UUID)).to.be.undefined
}
})
it('Should have the video unfederated even after an Update AP message', async function () {
this.timeout(10000)
- await updateVideo(servers[0].url, servers[0].accessToken, video4UUID, { description: 'super description' })
+ await servers[0].videos.update({ id: video4UUID, attributes: { description: 'super description' } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined
+ const { data } = await server.videos.list()
+ expect(data.find(v => v.uuid === video4UUID)).to.be.undefined
}
})
it('Should have the correct video blacklist unfederate attribute', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken, sort: 'createdAt' })
+ const body = await command.list({ sort: 'createdAt' })
- const blacklistedVideos: VideoBlacklist[] = res.body.data
+ const blacklistedVideos = body.data
const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID)
const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID)
it('Should remove the video from blacklist and refederate the video', async function () {
this.timeout(10000)
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, video4UUID)
+ await command.remove({ videoId: video4UUID })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.data.find(v => v.uuid === video4UUID)).to.not.be.undefined
+ const { data } = await server.videos.list()
+ expect(data.find(v => v.uuid === video4UUID)).to.not.be.undefined
}
})
before(async function () {
this.timeout(20000)
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
const config = {
auto_blacklist: {
}
}
}
- await reRunServer(servers[0], config)
+ await servers[0].run(config)
{
const user = { username: 'user_without_flag', password: 'password' }
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].users.create({
username: user.username,
adminFlags: UserAdminFlag.NONE,
password: user.password,
role: UserRole.USER
})
- userWithoutFlag = await userLogin(servers[0], user)
+ userWithoutFlag = await servers[0].login.getAccessToken(user)
- const res = await getMyUserInformation(servers[0].url, userWithoutFlag)
- const body: User = res.body
- channelOfUserWithoutFlag = body.videoChannels[0].id
+ const { videoChannels } = await servers[0].users.getMyInfo({ token: userWithoutFlag })
+ channelOfUserWithoutFlag = videoChannels[0].id
}
{
const user = { username: 'user_with_flag', password: 'password' }
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].users.create({
username: user.username,
adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST,
password: user.password,
role: UserRole.USER
})
- userWithFlag = await userLogin(servers[0], user)
+ userWithFlag = await servers[0].login.getAccessToken(user)
}
await waitJobs(servers)
})
it('Should auto blacklist a video on upload', async function () {
- await uploadVideo(servers[0].url, userWithoutFlag, { name: 'blacklisted' })
-
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
- })
+ await servers[0].videos.upload({ token: userWithoutFlag, attributes: { name: 'blacklisted' } })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].video.name).to.equal('blacklisted')
+ const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
+ expect(body.total).to.equal(1)
+ expect(body.data[0].video.name).to.equal('blacklisted')
})
it('Should auto blacklist a video on URL import', async function () {
this.timeout(15000)
const attributes = {
- targetUrl: getGoodVideoUrl(),
+ targetUrl: FIXTURE_URLS.goodVideo,
name: 'URL import',
channelId: channelOfUserWithoutFlag
}
- await importVideo(servers[0].url, userWithoutFlag, attributes)
+ await servers[0].imports.importVideo({ token: userWithoutFlag, attributes })
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- sort: 'createdAt',
- type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
- })
-
- expect(res.body.total).to.equal(2)
- expect(res.body.data[1].video.name).to.equal('URL import')
+ const body = await command.list({ sort: 'createdAt', type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
+ expect(body.total).to.equal(2)
+ expect(body.data[1].video.name).to.equal('URL import')
})
it('Should auto blacklist a video on torrent import', async function () {
const attributes = {
- magnetUri: getMagnetURI(),
+ magnetUri: FIXTURE_URLS.magnet,
name: 'Torrent import',
channelId: channelOfUserWithoutFlag
}
- await importVideo(servers[0].url, userWithoutFlag, attributes)
-
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- sort: 'createdAt',
- type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
- })
+ await servers[0].imports.importVideo({ token: userWithoutFlag, attributes })
- expect(res.body.total).to.equal(3)
- expect(res.body.data[2].video.name).to.equal('Torrent import')
+ const body = await command.list({ sort: 'createdAt', type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
+ expect(body.total).to.equal(3)
+ expect(body.data[2].video.name).to.equal('Torrent import')
})
it('Should not auto blacklist a video on upload if the user has the bypass blacklist flag', async function () {
- await uploadVideo(servers[0].url, userWithFlag, { name: 'not blacklisted' })
-
- const res = await getBlacklistedVideosList({
- url: servers[0].url,
- token: servers[0].accessToken,
- type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
- })
+ await servers[0].videos.upload({ token: userWithFlag, attributes: { name: 'not blacklisted' } })
- expect(res.body.total).to.equal(3)
+ const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
+ expect(body.total).to.equal(3)
})
})
import 'mocha'
import { expect } from 'chai'
-import { MockJoinPeerTubeVersions } from '@shared/extra-utils/mock-servers/joinpeertube-versions'
-import { PluginType } from '@shared/models'
-import { cleanupTests, installPlugin, setPluginLatestVersion, setPluginVersion, wait } from '../../../../shared/extra-utils'
-import { ServerInfo } from '../../../../shared/extra-utils/index'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
import {
CheckerBaseParams,
checkNewPeerTubeVersion,
checkNewPluginVersion,
- prepareNotificationsTest
-} from '../../../../shared/extra-utils/users/user-notifications'
-import { UserNotification, UserNotificationType } from '../../../../shared/models/users'
+ cleanupTests,
+ MockJoinPeerTubeVersions,
+ MockSmtpServer,
+ PeerTubeServer,
+ prepareNotificationsTest,
+ wait
+} from '@shared/extra-utils'
+import { PluginType, UserNotification, UserNotificationType } from '@shared/models'
describe('Test admin notifications', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userNotifications: UserNotification[] = []
let adminNotifications: UserNotification[] = []
let emails: object[] = []
token: server.accessToken
}
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-theme-background-red'
- })
+ await server.plugins.install({ npmName: 'peertube-plugin-hello-world' })
+ await server.plugins.install({ npmName: 'peertube-theme-background-red' })
})
describe('Latest PeerTube version notification', function () {
joinPeerTubeServer.setLatestVersion('1.4.2')
await wait(3000)
- await checkNewPeerTubeVersion(baseParams, '1.4.2', 'absence')
+ await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '1.4.2', checkType: 'absence' })
})
it('Should send a notification to admins on new plugin version', async function () {
joinPeerTubeServer.setLatestVersion('15.4.2')
await wait(3000)
- await checkNewPeerTubeVersion(baseParams, '15.4.2', 'presence')
+ await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '15.4.2', checkType: 'presence' })
})
it('Should not send the same notification to admins', async function () {
joinPeerTubeServer.setLatestVersion('15.4.3')
await wait(3000)
- await checkNewPeerTubeVersion(baseParams, '15.4.3', 'presence')
+ await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '15.4.3', checkType: 'presence' })
expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
})
})
this.timeout(30000)
await wait(6000)
- await checkNewPluginVersion(baseParams, PluginType.PLUGIN, 'hello-world', 'absence')
+ await checkNewPluginVersion({ ...baseParams, pluginType: PluginType.PLUGIN, pluginName: 'hello-world', checkType: 'absence' })
})
it('Should send a notification to admins on new plugin version', async function () {
this.timeout(30000)
- await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
- await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1')
+ await server.sql.setPluginVersion('hello-world', '0.0.1')
+ await server.sql.setPluginLatestVersion('hello-world', '0.0.1')
await wait(6000)
- await checkNewPluginVersion(baseParams, PluginType.PLUGIN, 'hello-world', 'presence')
+ await checkNewPluginVersion({ ...baseParams, pluginType: PluginType.PLUGIN, pluginName: 'hello-world', checkType: 'presence' })
})
it('Should not send the same notification to admins', async function () {
it('Should send a new notification after a new plugin release', async function () {
this.timeout(30000)
- await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
- await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1')
+ await server.sql.setPluginVersion('hello-world', '0.0.1')
+ await server.sql.setPluginLatestVersion('hello-world', '0.0.1')
await wait(6000)
expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
import 'mocha'
import * as chai from 'chai'
import {
- addAccountToAccountBlocklist,
- addVideoCommentReply,
- addVideoCommentThread,
checkCommentMention,
CheckerBaseParams,
checkNewCommentOnMyVideo,
cleanupTests,
- getVideoCommentThreads,
- getVideoThreadComments,
MockSmtpServer,
+ PeerTubeServer,
prepareNotificationsTest,
- removeAccountFromAccountBlocklist,
- ServerInfo,
- updateMyUser,
- uploadVideo,
waitJobs
} from '@shared/extra-utils'
-import { UserNotification, VideoCommentThreadTree } from '@shared/models'
+import { UserNotification } from '@shared/models'
const expect = chai.expect
describe('Test comments notifications', function () {
- let servers: ServerInfo[] = []
- let userAccessToken: string
+ let servers: PeerTubeServer[] = []
+ let userToken: string
let userNotifications: UserNotification[] = []
let emails: object[] = []
const res = await prepareNotificationsTest(2)
emails = res.emails
- userAccessToken = res.userAccessToken
+ userToken = res.userAccessToken
servers = res.servers
userNotifications = res.userNotifications
})
server: servers[0],
emails,
socketNotifications: userNotifications,
- token: userAccessToken
+ token: userToken
}
})
it('Should not send a new comment notification after a comment on another video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
- const commentId = resComment.body.comment.id
+ const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
+ const commentId = created.id
await waitJobs(servers)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
})
it('Should not send a new comment notification if I comment my own video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, uuid, 'comment')
- const commentId = resComment.body.comment.id
+ const created = await servers[0].comments.createThread({ token: userToken, videoId: uuid, text: 'comment' })
+ const commentId = created.id
await waitJobs(servers)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
})
it('Should not send a new comment notification if the account is muted', async function () {
this.timeout(20000)
- await addAccountToAccountBlocklist(servers[0].url, userAccessToken, 'root')
+ await servers[0].blocklist.addToMyBlocklist({ token: userToken, account: 'root' })
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
- const commentId = resComment.body.comment.id
+ const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
+ const commentId = created.id
await waitJobs(servers)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
- await removeAccountFromAccountBlocklist(servers[0].url, userAccessToken, 'root')
+ await servers[0].blocklist.removeFromMyBlocklist({ token: userToken, account: 'root' })
})
it('Should send a new comment notification after a local comment on my video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
- const commentId = resComment.body.comment.id
+ const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
+ const commentId = created.id
await waitJobs(servers)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'presence' })
})
it('Should send a new comment notification after a remote comment on my video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
await waitJobs(servers)
- await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment')
+ await servers[1].comments.createThread({ videoId: uuid, text: 'comment' })
await waitJobs(servers)
- const resComment = await getVideoCommentThreads(servers[0].url, uuid, 0, 5)
- expect(resComment.body.data).to.have.lengthOf(1)
- const commentId = resComment.body.data[0].id
+ const { data } = await servers[0].comments.listThreads({ videoId: uuid })
+ expect(data).to.have.lengthOf(1)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence')
+ const commentId = data[0].id
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'presence' })
})
it('Should send a new comment notification after a local reply on my video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
- const threadId = resThread.body.comment.id
+ const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
- const resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, 'reply')
- const commentId = resComment.body.comment.id
+ const { id: commentId } = await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'reply' })
await waitJobs(servers)
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId, commentId, checkType: 'presence' })
})
it('Should send a new comment notification after a remote reply on my video', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
await waitJobs(servers)
{
- const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment')
- const threadId = resThread.body.comment.id
- await addVideoCommentReply(servers[1].url, servers[1].accessToken, uuid, threadId, 'reply')
+ const created = await servers[1].comments.createThread({ videoId: uuid, text: 'comment' })
+ const threadId = created.id
+ await servers[1].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'reply' })
}
await waitJobs(servers)
- const resThread = await getVideoCommentThreads(servers[0].url, uuid, 0, 5)
- expect(resThread.body.data).to.have.lengthOf(1)
- const threadId = resThread.body.data[0].id
+ const { data } = await servers[0].comments.listThreads({ videoId: uuid })
+ expect(data).to.have.lengthOf(1)
- const resComments = await getVideoThreadComments(servers[0].url, uuid, threadId)
- const tree = resComments.body as VideoCommentThreadTree
+ const threadId = data[0].id
+ const tree = await servers[0].comments.getThread({ videoId: uuid, threadId })
expect(tree.children).to.have.lengthOf(1)
const commentId = tree.children[0].comment.id
- await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence')
+ await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId, commentId, checkType: 'presence' })
})
it('Should convert markdown in comment to html', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'cool video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'cool video' } })
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, commentText)
+ await servers[0].comments.createThread({ videoId: uuid, text: commentText })
await waitJobs(servers)
describe('Mention notifications', function () {
let baseParams: CheckerBaseParams
+ const byAccountDisplayName = 'super root name'
before(async () => {
baseParams = {
server: servers[0],
emails,
socketNotifications: userNotifications,
- token: userAccessToken
+ token: userToken
}
- await updateMyUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- displayName: 'super root name'
- })
-
- await updateMyUser({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
- displayName: 'super root 2 name'
- })
+ await servers[0].users.updateMe({ displayName: 'super root name' })
+ await servers[1].users.updateMe({ displayName: 'super root 2 name' })
})
it('Should not send a new mention comment notification if I mention the video owner', async function () {
this.timeout(10000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello')
- const commentId = resComment.body.comment.id
+ const { id: commentId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence')
+ await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
})
it('Should not send a new mention comment notification if I mention myself', async function () {
this.timeout(10000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, uuid, '@user_1 hello')
- const commentId = resComment.body.comment.id
+ const { id: commentId } = await servers[0].comments.createThread({ token: userToken, videoId: uuid, text: '@user_1 hello' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence')
+ await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
})
it('Should not send a new mention notification if the account is muted', async function () {
this.timeout(10000)
- await addAccountToAccountBlocklist(servers[0].url, userAccessToken, 'root')
+ await servers[0].blocklist.addToMyBlocklist({ token: userToken, account: 'root' })
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
- const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello')
- const commentId = resComment.body.comment.id
+ const { id: commentId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence')
+ await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
- await removeAccountFromAccountBlocklist(servers[0].url, userAccessToken, 'root')
+ await servers[0].blocklist.removeFromMyBlocklist({ token: userToken, account: 'root' })
})
it('Should not send a new mention notification if the remote account mention a local account', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
await waitJobs(servers)
- const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, '@user_1 hello')
- const threadId = resThread.body.comment.id
+ const { id: threadId } = await servers[1].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, threadId, threadId, 'super root 2 name', 'absence')
+
+ const byAccountDisplayName = 'super root 2 name'
+ await checkCommentMention({ ...baseParams, shortUUID, threadId, commentId: threadId, byAccountDisplayName, checkType: 'absence' })
})
it('Should send a new mention notification after local comments', async function () {
this.timeout(10000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
- const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello 1')
- const threadId = resThread.body.comment.id
+ const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hellotext: 1' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, threadId, threadId, 'super root name', 'presence')
+ await checkCommentMention({ ...baseParams, shortUUID, threadId, commentId: threadId, byAccountDisplayName, checkType: 'presence' })
- const resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, 'hello 2 @user_1')
- const commentId = resComment.body.comment.id
+ const { id: commentId } = await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'hello 2 @user_1' })
await waitJobs(servers)
- await checkCommentMention(baseParams, uuid, commentId, threadId, 'super root name', 'presence')
+ await checkCommentMention({ ...baseParams, shortUUID, commentId, threadId, byAccountDisplayName, checkType: 'presence' })
})
it('Should send a new mention notification after remote comments', async function () {
this.timeout(20000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
await waitJobs(servers)
const text1 = `hello @user_1@localhost:${servers[0].port} 1`
- const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, text1)
- const server2ThreadId = resThread.body.comment.id
+ const { id: server2ThreadId } = await servers[1].comments.createThread({ videoId: uuid, text: text1 })
await waitJobs(servers)
- const resThread2 = await getVideoCommentThreads(servers[0].url, uuid, 0, 5)
- expect(resThread2.body.data).to.have.lengthOf(1)
- const server1ThreadId = resThread2.body.data[0].id
- await checkCommentMention(baseParams, uuid, server1ThreadId, server1ThreadId, 'super root 2 name', 'presence')
+ const { data } = await servers[0].comments.listThreads({ videoId: uuid })
+ expect(data).to.have.lengthOf(1)
+
+ const byAccountDisplayName = 'super root 2 name'
+ const threadId = data[0].id
+ await checkCommentMention({ ...baseParams, shortUUID, commentId: threadId, threadId, byAccountDisplayName, checkType: 'presence' })
const text2 = `@user_1@localhost:${servers[0].port} hello 2 @root@localhost:${servers[0].port}`
- await addVideoCommentReply(servers[1].url, servers[1].accessToken, uuid, server2ThreadId, text2)
+ await servers[1].comments.addReply({ videoId: uuid, toCommentId: server2ThreadId, text: text2 })
await waitJobs(servers)
- const resComments = await getVideoThreadComments(servers[0].url, uuid, server1ThreadId)
- const tree = resComments.body as VideoCommentThreadTree
+ const tree = await servers[0].comments.getThread({ videoId: uuid, threadId })
expect(tree.children).to.have.lengthOf(1)
const commentId = tree.children[0].comment.id
- await checkCommentMention(baseParams, uuid, commentId, server1ThreadId, 'super root 2 name', 'presence')
+ await checkCommentMention({ ...baseParams, shortUUID, commentId, threadId, byAccountDisplayName, checkType: 'presence' })
})
it('Should convert markdown in comment to html', async function () {
this.timeout(10000)
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
- const uuid = resVideo.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
- const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello 1')
- const threadId = resThread.body.comment.id
+ const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello 1' })
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, '@user_1 ' + commentText)
+ await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: '@user_1 ' + commentText })
await waitJobs(servers)
import 'mocha'
import { buildUUID } from '@server/helpers/uuid'
-import { AbuseState } from '@shared/models'
-import {
- addAbuseMessage,
- addVideoCommentThread,
- addVideoToBlacklist,
- cleanupTests,
- createUser,
- follow,
- generateUserAccessToken,
- getAccount,
- getCustomConfig,
- getVideoCommentThreads,
- getVideoIdFromUUID,
- immutableAssign,
- MockInstancesIndex,
- registerUser,
- removeVideoFromBlacklist,
- reportAbuse,
- unfollow,
- updateAbuse,
- updateCustomConfig,
- updateCustomSubConfig,
- wait
-} from '../../../../shared/extra-utils'
-import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
import {
checkAbuseStateChange,
checkAutoInstanceFollowing,
checkUserRegistered,
checkVideoAutoBlacklistForModerators,
checkVideoIsPublished,
- prepareNotificationsTest
-} from '../../../../shared/extra-utils/users/user-notifications'
-import { addUserSubscription, removeUserSubscription } from '../../../../shared/extra-utils/users/user-subscriptions'
-import { CustomConfig } from '../../../../shared/models/server'
-import { UserNotification } from '../../../../shared/models/users'
-import { VideoPrivacy } from '../../../../shared/models/videos'
+ cleanupTests,
+ MockInstancesIndex,
+ MockSmtpServer,
+ PeerTubeServer,
+ prepareNotificationsTest,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { AbuseState, CustomConfig, UserNotification, VideoPrivacy } from '@shared/models'
describe('Test moderation notifications', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let userAccessToken: string
let userNotifications: UserNotification[] = []
let adminNotifications: UserNotification[] = []
this.timeout(20000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: video.id, reason: 'super reason' })
+ await servers[0].abuses.report({ videoId: video.id, reason: 'super reason' })
await waitJobs(servers)
- await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
+ await checkNewVideoAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
})
it('Should send a notification to moderators on remote video abuse', async function () {
this.timeout(20000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
await waitJobs(servers)
- const videoId = await getVideoIdFromUUID(servers[1].url, video.uuid)
- await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'super reason' })
+ const videoId = await servers[1].videos.getId({ uuid: video.uuid })
+ await servers[1].abuses.report({ videoId, reason: 'super reason' })
await waitJobs(servers)
- await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
+ await checkNewVideoAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
})
it('Should send a notification to moderators on local comment abuse', async function () {
this.timeout(20000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
- const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + buildUUID())
- const comment = resComment.body.comment
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
+ const comment = await servers[0].comments.createThread({
+ token: userAccessToken,
+ videoId: video.id,
+ text: 'comment abuse ' + buildUUID()
+ })
await waitJobs(servers)
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason: 'super reason' })
+ await servers[0].abuses.report({ commentId: comment.id, reason: 'super reason' })
await waitJobs(servers)
- await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
+ await checkNewCommentAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
})
it('Should send a notification to moderators on remote comment abuse', async function () {
this.timeout(20000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
- await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + buildUUID())
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
+
+ await servers[0].comments.createThread({
+ token: userAccessToken,
+ videoId: video.id,
+ text: 'comment abuse ' + buildUUID()
+ })
await waitJobs(servers)
- const resComments = await getVideoCommentThreads(servers[1].url, video.uuid, 0, 5)
- const commentId = resComments.body.data[0].id
- await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, commentId, reason: 'super reason' })
+ const { data } = await servers[1].comments.listThreads({ videoId: video.uuid })
+ const commentId = data[0].id
+ await servers[1].abuses.report({ commentId, reason: 'super reason' })
await waitJobs(servers)
- await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
+ await checkNewCommentAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
})
it('Should send a notification to moderators on local account abuse', async function () {
this.timeout(20000)
const username = 'user' + new Date().getTime()
- const resUser = await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username, password: 'donald' })
- const accountId = resUser.body.user.account.id
+ const { account } = await servers[0].users.create({ username, password: 'donald' })
+ const accountId = account.id
- await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId, reason: 'super reason' })
+ await servers[0].abuses.report({ accountId, reason: 'super reason' })
await waitJobs(servers)
- await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
+ await checkNewAccountAbuseForModerators({ ...baseParams, displayName: username, checkType: 'presence' })
})
it('Should send a notification to moderators on remote account abuse', async function () {
this.timeout(20000)
const username = 'user' + new Date().getTime()
- const tmpToken = await generateUserAccessToken(servers[0], username)
- await uploadVideo(servers[0].url, tmpToken, { name: 'super video' })
+ const tmpToken = await servers[0].users.generateUserAndToken(username)
+ await servers[0].videos.upload({ token: tmpToken, attributes: { name: 'super video' } })
await waitJobs(servers)
- const resAccount = await getAccount(servers[1].url, username + '@' + servers[0].host)
- await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, accountId: resAccount.body.id, reason: 'super reason' })
+ const account = await servers[1].accounts.get({ accountName: username + '@' + servers[0].host })
+ await servers[1].abuses.report({ accountId: account.id, reason: 'super reason' })
await waitJobs(servers)
- await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
+ await checkNewAccountAbuseForModerators({ ...baseParams, displayName: username, checkType: 'presence' })
})
})
}
const name = 'abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
- const res = await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: video.id, reason: 'super reason' })
- abuseId = res.body.abuse.id
+ const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
+ abuseId = body.abuse.id
})
it('Should send a notification to reporter if the abuse has been accepted', async function () {
this.timeout(10000)
- await updateAbuse(servers[0].url, servers[0].accessToken, abuseId, { state: AbuseState.ACCEPTED })
+ await servers[0].abuses.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
await waitJobs(servers)
- await checkAbuseStateChange(baseParams, abuseId, AbuseState.ACCEPTED, 'presence')
+ await checkAbuseStateChange({ ...baseParams, abuseId, state: AbuseState.ACCEPTED, checkType: 'presence' })
})
it('Should send a notification to reporter if the abuse has been rejected', async function () {
this.timeout(10000)
- await updateAbuse(servers[0].url, servers[0].accessToken, abuseId, { state: AbuseState.REJECTED })
+ await servers[0].abuses.update({ abuseId, body: { state: AbuseState.REJECTED } })
await waitJobs(servers)
- await checkAbuseStateChange(baseParams, abuseId, AbuseState.REJECTED, 'presence')
+ await checkAbuseStateChange({ ...baseParams, abuseId, state: AbuseState.REJECTED, checkType: 'presence' })
})
})
}
const name = 'abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const video = resVideo.body.video
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
{
- const res = await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: video.id, reason: 'super reason' })
- abuseId = res.body.abuse.id
+ const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
+ abuseId = body.abuse.id
}
{
- const res = await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: video.id, reason: 'super reason 2' })
- abuseId2 = res.body.abuse.id
+ const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason 2' })
+ abuseId2 = body.abuse.id
}
})
this.timeout(10000)
const message = 'my super message to users'
- await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, message)
+ await servers[0].abuses.addMessage({ abuseId, message })
await waitJobs(servers)
- await checkNewAbuseMessage(baseParamsUser, abuseId, message, 'user_1@example.com', 'presence')
+ await checkNewAbuseMessage({ ...baseParamsUser, abuseId, message, toEmail: 'user_1@example.com', checkType: 'presence' })
})
it('Should not send a notification to the admin if sent by the admin', async function () {
this.timeout(10000)
const message = 'my super message that should not be sent to the admin'
- await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, message)
+ await servers[0].abuses.addMessage({ abuseId, message })
await waitJobs(servers)
- await checkNewAbuseMessage(baseParamsAdmin, abuseId, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'absence')
+ const toEmail = 'admin' + servers[0].internalServerNumber + '@example.com'
+ await checkNewAbuseMessage({ ...baseParamsAdmin, abuseId, message, toEmail, checkType: 'absence' })
})
it('Should send a notification to moderators', async function () {
this.timeout(10000)
const message = 'my super message to moderators'
- await addAbuseMessage(servers[0].url, userAccessToken, abuseId2, message)
+ await servers[0].abuses.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
await waitJobs(servers)
- await checkNewAbuseMessage(baseParamsAdmin, abuseId2, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'presence')
+ const toEmail = 'admin' + servers[0].internalServerNumber + '@example.com'
+ await checkNewAbuseMessage({ ...baseParamsAdmin, abuseId: abuseId2, message, toEmail, checkType: 'presence' })
})
it('Should not send a notification to reporter if sent by the reporter', async function () {
this.timeout(10000)
const message = 'my super message that should not be sent to reporter'
- await addAbuseMessage(servers[0].url, userAccessToken, abuseId2, message)
+ await servers[0].abuses.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
await waitJobs(servers)
- await checkNewAbuseMessage(baseParamsUser, abuseId2, message, 'user_1@example.com', 'absence')
+ const toEmail = 'user_1@example.com'
+ await checkNewAbuseMessage({ ...baseParamsUser, abuseId: abuseId2, message, toEmail, checkType: 'absence' })
})
})
this.timeout(10000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
+ await servers[0].blacklist.add({ videoId: uuid })
await waitJobs(servers)
- await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist')
+ await checkNewBlacklistOnMyVideo({ ...baseParams, shortUUID, videoName: name, blacklistType: 'blacklist' })
})
it('Should send a notification to video owner on unblacklist', async function () {
this.timeout(10000)
const name = 'video for abuse ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
- const uuid = resVideo.body.video.uuid
+ const { uuid, shortUUID } = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
+ await servers[0].blacklist.add({ videoId: uuid })
await waitJobs(servers)
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid)
+ await servers[0].blacklist.remove({ videoId: uuid })
await waitJobs(servers)
await wait(500)
- await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist')
+ await checkNewBlacklistOnMyVideo({ ...baseParams, shortUUID, videoName: name, blacklistType: 'unblacklist' })
})
})
it('Should send a notification only to moderators when a user registers on the instance', async function () {
this.timeout(10000)
- await registerUser(servers[0].url, 'user_45', 'password')
+ await servers[0].users.register({ username: 'user_45' })
await waitJobs(servers)
- await checkUserRegistered(baseParams, 'user_45', 'presence')
+ await checkUserRegistered({ ...baseParams, username: 'user_45', checkType: 'presence' })
const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
- await checkUserRegistered(immutableAssign(baseParams, userOverride), 'user_45', 'absence')
+ await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_45', checkType: 'absence' })
})
})
it('Should send a notification only to admin when there is a new instance follower', async function () {
this.timeout(20000)
- await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
+ await servers[2].follows.follow({ hosts: [ servers[0].url ] })
await waitJobs(servers)
- await checkNewInstanceFollower(baseParams, 'localhost:' + servers[2].port, 'presence')
+ await checkNewInstanceFollower({ ...baseParams, followerHost: 'localhost:' + servers[2].port, checkType: 'presence' })
const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
- await checkNewInstanceFollower(immutableAssign(baseParams, userOverride), 'localhost:' + servers[2].port, 'absence')
+ await checkNewInstanceFollower({ ...baseParams, ...userOverride, followerHost: 'localhost:' + servers[2].port, checkType: 'absence' })
})
it('Should send a notification on auto follow back', async function () {
this.timeout(40000)
- await unfollow(servers[2].url, servers[2].accessToken, servers[0])
+ await servers[2].follows.unfollow({ target: servers[0] })
await waitJobs(servers)
const config = {
}
}
}
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
- await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
+ await servers[2].follows.follow({ hosts: [ servers[0].url ] })
await waitJobs(servers)
const followerHost = servers[0].host
const followingHost = servers[2].host
- await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
+ await checkAutoInstanceFollowing({ ...baseParams, followerHost, followingHost, checkType: 'presence' })
const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
- await checkAutoInstanceFollowing(immutableAssign(baseParams, userOverride), followerHost, followingHost, 'absence')
+ await checkAutoInstanceFollowing({ ...baseParams, ...userOverride, followerHost, followingHost, checkType: 'absence' })
config.followings.instance.autoFollowBack.enabled = false
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
- await unfollow(servers[0].url, servers[0].accessToken, servers[2])
- await unfollow(servers[2].url, servers[2].accessToken, servers[0])
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
+ await servers[0].follows.unfollow({ target: servers[2] })
+ await servers[2].follows.unfollow({ target: servers[0] })
})
it('Should send a notification on auto instances index follow', async function () {
this.timeout(30000)
- await unfollow(servers[0].url, servers[0].accessToken, servers[1])
+ await servers[0].follows.unfollow({ target: servers[1] })
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
await wait(5000)
await waitJobs(servers)
const followerHost = servers[0].host
const followingHost = servers[1].host
- await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
+ await checkAutoInstanceFollowing({ ...baseParams, followerHost, followingHost, checkType: 'presence' })
config.followings.instance.autoFollowIndex.enabled = false
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
- await unfollow(servers[0].url, servers[0].accessToken, servers[1])
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
+ await servers[0].follows.unfollow({ target: servers[1] })
})
})
let userBaseParams: CheckerBaseParams
let adminBaseParamsServer1: CheckerBaseParams
let adminBaseParamsServer2: CheckerBaseParams
- let videoUUID: string
+ let uuid: string
+ let shortUUID: string
let videoName: string
let currentCustomConfig: CustomConfig
token: userAccessToken
}
- const resCustomConfig = await getCustomConfig(servers[0].url, servers[0].accessToken)
- currentCustomConfig = resCustomConfig.body
- const autoBlacklistTestsCustomConfig = immutableAssign(currentCustomConfig, {
+ currentCustomConfig = await servers[0].config.getCustomConfig()
+
+ const autoBlacklistTestsCustomConfig = {
+ ...currentCustomConfig,
+
autoBlacklist: {
videos: {
ofUsers: {
}
}
}
- })
+ }
+
// enable transcoding otherwise own publish notification after transcoding not expected
autoBlacklistTestsCustomConfig.transcoding.enabled = true
- await updateCustomConfig(servers[0].url, servers[0].accessToken, autoBlacklistTestsCustomConfig)
-
- await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
- await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[0].config.updateCustomConfig({ newCustomConfig: autoBlacklistTestsCustomConfig })
+ await servers[0].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
+ await servers[1].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
})
it('Should send notification to moderators on new video with auto-blacklist', async function () {
this.timeout(40000)
videoName = 'video with auto-blacklist ' + buildUUID()
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
- videoUUID = resVideo.body.video.uuid
+ const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name: videoName } })
+ shortUUID = video.shortUUID
+ uuid = video.uuid
await waitJobs(servers)
- await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, videoUUID, videoName, 'presence')
+ await checkVideoAutoBlacklistForModerators({ ...adminBaseParamsServer1, shortUUID, videoName, checkType: 'presence' })
})
it('Should not send video publish notification if auto-blacklisted', async function () {
- await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'absence')
+ await checkVideoIsPublished({ ...userBaseParams, videoName, shortUUID, checkType: 'absence' })
})
it('Should not send a local user subscription notification if auto-blacklisted', async function () {
- await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'absence')
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName, shortUUID, checkType: 'absence' })
})
it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
- await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'absence')
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName, shortUUID, checkType: 'absence' })
})
it('Should send video published and unblacklist after video unblacklisted', async function () {
this.timeout(40000)
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoUUID)
+ await servers[0].blacklist.remove({ videoId: uuid })
await waitJobs(servers)
})
it('Should send a local user subscription notification after removed from blacklist', async function () {
- await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'presence')
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName, shortUUID, checkType: 'presence' })
})
it('Should send a remote user subscription notification after removed from blacklist', async function () {
- await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'presence')
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName, shortUUID, checkType: 'presence' })
})
it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
const name = 'video with auto-blacklist and future schedule ' + buildUUID()
- const data = {
+ const attributes = {
name,
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
- const uuid = resVideo.body.video.uuid
+ const { shortUUID, uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes })
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid)
+ await servers[0].blacklist.remove({ videoId: uuid })
await waitJobs(servers)
- await checkNewBlacklistOnMyVideo(userBaseParams, uuid, name, 'unblacklist')
+ await checkNewBlacklistOnMyVideo({ ...userBaseParams, shortUUID, videoName: name, blacklistType: 'unblacklist' })
// FIXME: Can't test absence as two notifications sent to same user and util only checks last one
// One notification might be better anyways
// await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
- await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
- await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName: name, shortUUID, checkType: 'absence' })
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
const name = 'video with schedule done and still auto-blacklisted ' + buildUUID()
- const data = {
+ const attributes = {
name,
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
- const uuid = resVideo.body.video.uuid
+ const { shortUUID } = await servers[0].videos.upload({ token: userAccessToken, attributes })
await wait(6000)
- await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
- await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
- await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
+ await checkVideoIsPublished({ ...userBaseParams, videoName: name, shortUUID, checkType: 'absence' })
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName: name, shortUUID, checkType: 'absence' })
+ await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
const name = 'video without auto-blacklist ' + buildUUID()
// admin with blacklist right will not be auto-blacklisted
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name })
- const uuid = resVideo.body.video.uuid
+ const { shortUUID } = await servers[0].videos.upload({ attributes: { name } })
await waitJobs(servers)
- await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, uuid, name, 'absence')
+ await checkVideoAutoBlacklistForModerators({ ...adminBaseParamsServer1, shortUUID, videoName: name, checkType: 'absence' })
})
after(async () => {
- await updateCustomConfig(servers[0].url, servers[0].accessToken, currentCustomConfig)
+ await servers[0].config.updateCustomConfig({ newCustomConfig: currentCustomConfig })
- await removeUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
- await removeUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
+ await servers[1].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
})
})
import 'mocha'
import * as chai from 'chai'
-import { addUserSubscription } from '@shared/extra-utils/users/user-subscriptions'
-import { cleanupTests, getMyUserInformation, immutableAssign, uploadRandomVideo, waitJobs } from '../../../../shared/extra-utils'
-import { ServerInfo } from '../../../../shared/extra-utils/index'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
import {
CheckerBaseParams,
checkNewVideoFromSubscription,
+ cleanupTests,
getAllNotificationsSettings,
- getUserNotifications,
- markAsReadAllNotifications,
- markAsReadNotifications,
+ MockSmtpServer,
+ PeerTubeServer,
prepareNotificationsTest,
- updateMyNotificationSettings
-} from '../../../../shared/extra-utils/users/user-notifications'
-import { User, UserNotification, UserNotificationSettingValue } from '../../../../shared/models/users'
+ waitJobs
+} from '@shared/extra-utils'
+import { UserNotification, UserNotificationSettingValue } from '@shared/models'
const expect = chai.expect
describe('Test notifications API', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userNotifications: UserNotification[] = []
- let userAccessToken: string
+ let userToken: string
let emails: object[] = []
before(async function () {
const res = await prepareNotificationsTest(1)
emails = res.emails
- userAccessToken = res.userAccessToken
+ userToken = res.userAccessToken
userNotifications = res.userNotifications
server = res.servers[0]
- await addUserSubscription(server.url, userAccessToken, 'root_channel@localhost:' + server.port)
+ await server.subscriptions.add({ token: userToken, targetUri: 'root_channel@localhost:' + server.port })
for (let i = 0; i < 10; i++) {
- await uploadRandomVideo(server, false)
+ await server.videos.randomUpload({ wait: false })
}
await waitJobs([ server ])
describe('Mark as read', function () {
it('Should mark as read some notifications', async function () {
- const res = await getUserNotifications(server.url, userAccessToken, 2, 3)
- const ids = res.body.data.map(n => n.id)
+ const { data } = await server.notifications.list({ token: userToken, start: 2, count: 3 })
+ const ids = data.map(n => n.id)
- await markAsReadNotifications(server.url, userAccessToken, ids)
+ await server.notifications.markAsRead({ token: userToken, ids })
})
it('Should have the notifications marked as read', async function () {
- const res = await getUserNotifications(server.url, userAccessToken, 0, 10)
-
- const notifications = res.body.data as UserNotification[]
- expect(notifications[0].read).to.be.false
- expect(notifications[1].read).to.be.false
- expect(notifications[2].read).to.be.true
- expect(notifications[3].read).to.be.true
- expect(notifications[4].read).to.be.true
- expect(notifications[5].read).to.be.false
+ const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10 })
+
+ expect(data[0].read).to.be.false
+ expect(data[1].read).to.be.false
+ expect(data[2].read).to.be.true
+ expect(data[3].read).to.be.true
+ expect(data[4].read).to.be.true
+ expect(data[5].read).to.be.false
})
it('Should only list read notifications', async function () {
- const res = await getUserNotifications(server.url, userAccessToken, 0, 10, false)
+ const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: false })
- const notifications = res.body.data as UserNotification[]
- for (const notification of notifications) {
+ for (const notification of data) {
expect(notification.read).to.be.true
}
})
it('Should only list unread notifications', async function () {
- const res = await getUserNotifications(server.url, userAccessToken, 0, 10, true)
+ const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: true })
- const notifications = res.body.data as UserNotification[]
- for (const notification of notifications) {
+ for (const notification of data) {
expect(notification.read).to.be.false
}
})
it('Should mark as read all notifications', async function () {
- await markAsReadAllNotifications(server.url, userAccessToken)
+ await server.notifications.markAsReadAll({ token: userToken })
- const res = await getUserNotifications(server.url, userAccessToken, 0, 10, true)
+ const body = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: true })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
})
server: server,
emails,
socketNotifications: userNotifications,
- token: userAccessToken
+ token: userToken
}
})
it('Should not have notifications', async function () {
this.timeout(20000)
- await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), {
- newVideoFromSubscription: UserNotificationSettingValue.NONE
- }))
+ await server.notifications.updateMySettings({
+ token: userToken,
+ settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.NONE }
+ })
{
- const res = await getMyUserInformation(server.url, userAccessToken)
- const info = res.body as User
+ const info = await server.users.getMyInfo({ token: userToken })
expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE)
}
- const { name, uuid } = await uploadRandomVideo(server)
+ const { name, shortUUID } = await server.videos.randomUpload()
const check = { web: true, mail: true }
- await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should only have web notifications', async function () {
this.timeout(20000)
- await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), {
- newVideoFromSubscription: UserNotificationSettingValue.WEB
- }))
+ await server.notifications.updateMySettings({
+ token: userToken,
+ settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.WEB }
+ })
{
- const res = await getMyUserInformation(server.url, userAccessToken)
- const info = res.body as User
+ const info = await server.users.getMyInfo({ token: userToken })
expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB)
}
- const { name, uuid } = await uploadRandomVideo(server)
+ const { name, shortUUID } = await server.videos.randomUpload()
{
const check = { mail: true, web: false }
- await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
}
{
const check = { mail: false, web: true }
- await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'presence' })
}
})
it('Should only have mail notifications', async function () {
this.timeout(20000)
- await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), {
- newVideoFromSubscription: UserNotificationSettingValue.EMAIL
- }))
+ await server.notifications.updateMySettings({
+ token: userToken,
+ settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.EMAIL }
+ })
{
- const res = await getMyUserInformation(server.url, userAccessToken)
- const info = res.body as User
+ const info = await server.users.getMyInfo({ token: userToken })
expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL)
}
- const { name, uuid } = await uploadRandomVideo(server)
+ const { name, shortUUID } = await server.videos.randomUpload()
{
const check = { mail: false, web: true }
- await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
}
{
const check = { mail: true, web: false }
- await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'presence' })
}
})
it('Should have email and web notifications', async function () {
this.timeout(20000)
- await updateMyNotificationSettings(server.url, userAccessToken, immutableAssign(getAllNotificationsSettings(), {
- newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
- }))
+ await server.notifications.updateMySettings({
+ token: userToken,
+ settings: {
+ ...getAllNotificationsSettings(),
+ newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
+ }
+ })
{
- const res = await getMyUserInformation(server.url, userAccessToken)
- const info = res.body as User
+ const info = await server.users.getMyInfo({ token: userToken })
expect(info.notificationSettings.newVideoFromSubscription).to.equal(
UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
)
}
- const { name, uuid } = await uploadRandomVideo(server)
+ const { name, shortUUID } = await server.videos.randomUpload()
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
})
import 'mocha'
import * as chai from 'chai'
import { buildUUID } from '@server/helpers/uuid'
-import {
- cleanupTests,
- updateMyUser,
- updateVideo,
- updateVideoChannel,
- uploadRandomVideoOnServers,
- wait
-} from '../../../../shared/extra-utils'
-import { ServerInfo } from '../../../../shared/extra-utils/index'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
import {
CheckerBaseParams,
checkMyVideoImportIsFinished,
checkNewActorFollow,
checkNewVideoFromSubscription,
checkVideoIsPublished,
- getLastNotification,
- prepareNotificationsTest
-} from '../../../../shared/extra-utils/users/user-notifications'
-import { addUserSubscription, removeUserSubscription } from '../../../../shared/extra-utils/users/user-subscriptions'
-import { getBadVideoUrl, getGoodVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
-import { UserNotification, UserNotificationType } from '../../../../shared/models/users'
-import { VideoPrivacy } from '../../../../shared/models/videos'
+ cleanupTests,
+ FIXTURE_URLS,
+ MockSmtpServer,
+ PeerTubeServer,
+ prepareNotificationsTest,
+ uploadRandomVideoOnServers,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { UserNotification, UserNotificationType, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test user notifications', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let userAccessToken: string
let userNotifications: UserNotification[] = []
let adminNotifications: UserNotification[] = []
await uploadRandomVideoOnServers(servers, 1)
- const notification = await getLastNotification(servers[0].url, userAccessToken)
+ const notification = await servers[0].notifications.getLastest({ token: userAccessToken })
expect(notification).to.be.undefined
expect(emails).to.have.lengthOf(0)
it('Should send a new video notification if the user follows the local video publisher', async function () {
this.timeout(15000)
- await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@localhost:' + servers[0].port })
await waitJobs(servers)
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1)
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a new video notification from a remote account', async function () {
this.timeout(150000) // Server 2 has transcoding enabled
- await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:' + servers[1].port)
+ await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@localhost:' + servers[1].port })
await waitJobs(servers)
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2)
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a new video notification on a scheduled publication', async function () {
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1, data)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
await wait(6000)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a new video notification on a remote scheduled publication', async function () {
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, data)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
await waitJobs(servers)
await wait(6000)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should not send a notification before the video is published', async function () {
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1, data)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
await wait(6000)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should send a new video notification when a video becomes public', async function () {
this.timeout(50000)
const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1, data)
+ const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC })
+ await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
await waitJobs(servers)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a new video notification when a remote video becomes public', async function () {
this.timeout(50000)
const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, data)
+ const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC })
+ await servers[1].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
await waitJobs(servers)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should not send a new video notification when a video becomes unlisted', async function () {
this.timeout(50000)
const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1, data)
+ const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
- await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED })
+ await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should not send a new video notification when a remote video becomes unlisted', async function () {
this.timeout(50000)
const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, data)
+ const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
- await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED })
+ await servers[1].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
await waitJobs(servers)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should send a new video notification after a video import', async function () {
name,
channelId,
privacy: VideoPrivacy.PUBLIC,
- targetUrl: getGoodVideoUrl()
+ targetUrl: FIXTURE_URLS.goodVideo
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- const uuid = res.body.video.uuid
+ const { video } = await servers[0].imports.importVideo({ attributes })
await waitJobs(servers)
- await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence')
+ await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
})
})
it('Should not send a notification if transcoding is not enabled', async function () {
this.timeout(50000)
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 1)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1)
await waitJobs(servers)
- await checkVideoIsPublished(baseParams, name, uuid, 'absence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should not send a notification if the wait transcoding is false', async function () {
await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: false })
await waitJobs(servers)
- const notification = await getLastNotification(servers[0].url, userAccessToken)
+ const notification = await servers[0].notifications.getLastest({ token: userAccessToken })
if (notification) {
expect(notification.type).to.not.equal(UserNotificationType.MY_VIDEO_PUBLISHED)
}
it('Should send a notification even if the video is not transcoded in other resolutions', async function () {
this.timeout(50000)
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true, fixture: 'video_short_240p.mp4' })
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true, fixture: 'video_short_240p.mp4' })
await waitJobs(servers)
- await checkVideoIsPublished(baseParams, name, uuid, 'presence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a notification with a transcoded video', async function () {
this.timeout(50000)
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
await waitJobs(servers)
- await checkVideoIsPublished(baseParams, name, uuid, 'presence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a notification when an imported video is transcoded', async function () {
name,
channelId,
privacy: VideoPrivacy.PUBLIC,
- targetUrl: getGoodVideoUrl(),
+ targetUrl: FIXTURE_URLS.goodVideo,
waitTranscoding: true
}
- const res = await importVideo(servers[1].url, servers[1].accessToken, attributes)
- const uuid = res.body.video.uuid
+ const { video } = await servers[1].imports.importVideo({ attributes })
await waitJobs(servers)
- await checkVideoIsPublished(baseParams, name, uuid, 'presence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
})
it('Should send a notification when the scheduled update has been proceeded', async function () {
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, data)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
await wait(6000)
- await checkVideoIsPublished(baseParams, name, uuid, 'presence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should not send a notification before the video is published', async function () {
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- const { name, uuid } = await uploadRandomVideoOnServers(servers, 2, data)
+ const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
await wait(6000)
- await checkVideoIsPublished(baseParams, name, uuid, 'absence')
+ await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
})
name,
channelId,
privacy: VideoPrivacy.PRIVATE,
- targetUrl: getBadVideoUrl()
+ targetUrl: FIXTURE_URLS.badVideo
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- const uuid = res.body.video.uuid
+ const { video: { shortUUID } } = await servers[0].imports.importVideo({ attributes })
await waitJobs(servers)
- await checkMyVideoImportIsFinished(baseParams, name, uuid, getBadVideoUrl(), false, 'presence')
+
+ const url = FIXTURE_URLS.badVideo
+ await checkMyVideoImportIsFinished({ ...baseParams, videoName: name, shortUUID, url, success: false, checkType: 'presence' })
})
it('Should send a notification when the video import succeeded', async function () {
name,
channelId,
privacy: VideoPrivacy.PRIVATE,
- targetUrl: getGoodVideoUrl()
+ targetUrl: FIXTURE_URLS.goodVideo
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- const uuid = res.body.video.uuid
+ const { video: { shortUUID } } = await servers[0].imports.importVideo({ attributes })
await waitJobs(servers)
- await checkMyVideoImportIsFinished(baseParams, name, uuid, getGoodVideoUrl(), true, 'presence')
+
+ const url = FIXTURE_URLS.goodVideo
+ await checkMyVideoImportIsFinished({ ...baseParams, videoName: name, shortUUID, url, success: true, checkType: 'presence' })
})
})
token: userAccessToken
}
- await updateMyUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- displayName: 'super root name'
- })
+ await servers[0].users.updateMe({ displayName: 'super root name' })
- await updateMyUser({
- url: servers[0].url,
- accessToken: userAccessToken,
+ await servers[0].users.updateMe({
+ token: userAccessToken,
displayName: myUserName
})
- await updateMyUser({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
- displayName: 'super root 2 name'
- })
+ await servers[1].users.updateMe({ displayName: 'super root 2 name' })
- await updateVideoChannel(servers[0].url, userAccessToken, 'user_1_channel', { displayName: myChannelName })
+ await servers[0].channels.update({
+ token: userAccessToken,
+ channelName: 'user_1_channel',
+ attributes: { displayName: myChannelName }
+ })
})
it('Should notify when a local channel is following one of our channel', async function () {
this.timeout(50000)
- await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
await waitJobs(servers)
- await checkNewActorFollow(baseParams, 'channel', 'root', 'super root name', myChannelName, 'presence')
+ await checkNewActorFollow({
+ ...baseParams,
+ followType: 'channel',
+ followerName: 'root',
+ followerDisplayName: 'super root name',
+ followingDisplayName: myChannelName,
+ checkType: 'presence'
+ })
- await removeUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
})
it('Should notify when a remote channel is following one of our channel', async function () {
this.timeout(50000)
- await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[1].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
await waitJobs(servers)
- await checkNewActorFollow(baseParams, 'channel', 'root', 'super root 2 name', myChannelName, 'presence')
+ await checkNewActorFollow({
+ ...baseParams,
+ followType: 'channel',
+ followerName: 'root',
+ followerDisplayName: 'super root 2 name',
+ followingDisplayName: myChannelName,
+ checkType: 'presence'
+ })
- await removeUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
+ await servers[1].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
})
// PeerTube does not support accout -> account follows
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getLocalIdByUUID,
- ServerInfo,
+ PeerTubeServer,
+ RedundancyCommand,
setAccessTokensToServers,
- uploadVideo,
- uploadVideoAndGetId,
- waitUntilLog
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy, updateRedundancy } from '@shared/extra-utils/server/redundancy'
-import { VideoPrivacy, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPrivacy, VideoRedundanciesTarget } from '@shared/models'
const expect = chai.expect
describe('Test manage videos redundancy', function () {
const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let video1Server2UUID: string
let video2Server2UUID: string
let redundanciesToRemove: number[] = []
+ let commands: RedundancyCommand[]
+
before(async function () {
this.timeout(120000)
}
}
}
- servers = await flushAndRunMultipleServers(3, config)
+ servers = await createMultipleServers(3, config)
// Get the access tokens
await setAccessTokensToServers(servers)
+ commands = servers.map(s => s.redundancy)
+
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' })
- video1Server2UUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
+ video1Server2UUID = uuid
}
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 2 server 2' })
- video2Server2UUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2' } })
+ video2Server2UUID = uuid
}
await waitJobs(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
- await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, true)
+ await commands[0].updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
await waitJobs(servers)
})
it('Should not have redundancies on server 3', async function () {
for (const target of targets) {
- const res = await listVideoRedundancies({
- url: servers[2].url,
- accessToken: servers[2].accessToken,
- target
- })
+ const body = await commands[2].listVideos({ target })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
})
this.timeout(120000)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 10)
+ await servers[0].servers.waitUntilLog('Duplicated ', 10)
await waitJobs(servers)
- const res = await listVideoRedundancies({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
- target: 'remote-videos'
- })
+ const body = await commands[1].listVideos({ target: 'remote-videos' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should have "my-videos" redundancies on server 2', async function () {
this.timeout(120000)
- const res = await listVideoRedundancies({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
- target: 'my-videos'
- })
-
- expect(res.body.total).to.equal(2)
+ const body = await commands[1].listVideos({ target: 'my-videos' })
+ expect(body.total).to.equal(2)
- const videos = res.body.data as VideoRedundancy[]
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
const videos1 = videos.find(v => v.uuid === video1Server2UUID)
})
it('Should not have "my-videos" redundancies on server 1', async function () {
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- target: 'my-videos'
- })
+ const body = await commands[0].listVideos({ target: 'my-videos' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should have "remote-videos" redundancies on server 1', async function () {
this.timeout(120000)
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- target: 'remote-videos'
- })
+ const body = await commands[0].listVideos({ target: 'remote-videos' })
+ expect(body.total).to.equal(2)
- expect(res.body.total).to.equal(2)
-
- const videos = res.body.data as VideoRedundancy[]
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
const videos1 = videos.find(v => v.uuid === video1Server2UUID)
it('Should correctly paginate and sort results', async function () {
{
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await commands[0].listVideos({
target: 'remote-videos',
sort: 'name',
start: 0,
count: 2
})
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 1 server 2')
expect(videos[1].name).to.equal('video 2 server 2')
}
{
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await commands[0].listVideos({
target: 'remote-videos',
sort: '-name',
start: 0,
count: 2
})
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 2 server 2')
expect(videos[1].name).to.equal('video 1 server 2')
}
{
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await commands[0].listVideos({
target: 'remote-videos',
sort: '-name',
start: 1,
count: 1
})
- const videos = res.body.data
- expect(videos[0].name).to.equal('video 1 server 2')
+ expect(body.data[0].name).to.equal('video 1 server 2')
}
})
it('Should manually add a redundancy and list it', async function () {
this.timeout(120000)
- const uuid = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
+ const uuid = (await servers[1].videos.quickUpload({ name: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
await waitJobs(servers)
- const videoId = await getLocalIdByUUID(servers[0].url, uuid)
+ const videoId = await servers[0].videos.getId({ uuid })
- await addVideoRedundancy({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoId
- })
+ await commands[0].addVideo({ videoId })
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 15)
+ await servers[0].servers.waitUntilLog('Duplicated ', 15)
await waitJobs(servers)
{
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await commands[0].listVideos({
target: 'remote-videos',
sort: '-name',
start: 0,
count: 5
})
- const videos = res.body.data
- expect(videos[0].name).to.equal('video 3 server 2')
+ const video = body.data[0]
- const video = videos[0]
+ expect(video.name).to.equal('video 3 server 2')
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
}
}
- const res = await listVideoRedundancies({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
+ const body = await commands[1].listVideos({
target: 'my-videos',
sort: '-name',
start: 0,
count: 5
})
- const videos = res.body.data
- expect(videos[0].name).to.equal('video 3 server 2')
-
- const video = videos[0]
+ const video = body.data[0]
+ expect(video.name).to.equal('video 3 server 2')
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
this.timeout(120000)
for (const redundancyId of redundanciesToRemove) {
- await removeVideoRedundancy({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- redundancyId
- })
+ await commands[0].removeVideo({ redundancyId })
}
{
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await commands[0].listVideos({
target: 'remote-videos',
sort: '-name',
start: 0,
count: 5
})
- const videos = res.body.data
- expect(videos).to.have.lengthOf(2)
+ const videos = body.data
- expect(videos[0].name).to.equal('video 2 server 2')
+ expect(videos).to.have.lengthOf(2)
- redundanciesToRemove = []
const video = videos[0]
+ expect(video.name).to.equal('video 2 server 2')
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
- for (const r of redundancies) {
- redundanciesToRemove.push(r.id)
- }
+ redundanciesToRemove = redundancies.map(r => r.id)
}
})
it('Should remove another (auto) redundancy', async function () {
- {
- for (const redundancyId of redundanciesToRemove) {
- await removeVideoRedundancy({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- redundancyId
- })
- }
+ for (const redundancyId of redundanciesToRemove) {
+ await commands[0].removeVideo({ redundancyId })
+ }
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- target: 'remote-videos',
- sort: '-name',
- start: 0,
- count: 5
- })
+ const body = await commands[0].listVideos({
+ target: 'remote-videos',
+ sort: '-name',
+ start: 0,
+ count: 5
+ })
- const videos = res.body.data
- expect(videos[0].name).to.equal('video 1 server 2')
- expect(videos).to.have.lengthOf(1)
- }
+ const videos = body.data
+ expect(videos).to.have.lengthOf(1)
+ expect(videos[0].name).to.equal('video 1 server 2')
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import * as chai from 'chai'
-import { listVideoRedundancies, updateRedundancy } from '@shared/extra-utils/server/redundancy'
+import { expect } from 'chai'
+import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- flushAndRunServer,
- follow,
- killallServers,
- reRunServer,
- ServerInfo,
- setAccessTokensToServers,
- updateVideo,
- uploadVideo,
- waitUntilLog
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-
-const expect = chai.expect
describe('Test redundancy constraints', function () {
- let remoteServer: ServerInfo
- let localServer: ServerInfo
- let servers: ServerInfo[]
+ let remoteServer: PeerTubeServer
+ let localServer: PeerTubeServer
+ let servers: PeerTubeServer[]
const remoteServerConfig = {
redundancy: {
async function uploadWrapper (videoName: string) {
// Wait for transcoding
- const res = await uploadVideo(localServer.url, localServer.accessToken, { name: 'to transcode', privacy: VideoPrivacy.PRIVATE })
+ const { id } = await localServer.videos.upload({ attributes: { name: 'to transcode', privacy: VideoPrivacy.PRIVATE } })
await waitJobs([ localServer ])
// Update video to schedule a federation
- await updateVideo(localServer.url, localServer.accessToken, res.body.video.id, { name: videoName, privacy: VideoPrivacy.PUBLIC })
+ await localServer.videos.update({ id, attributes: { name: videoName, privacy: VideoPrivacy.PUBLIC } })
}
async function getTotalRedundanciesLocalServer () {
- const res = await listVideoRedundancies({
- url: localServer.url,
- accessToken: localServer.accessToken,
- target: 'my-videos'
- })
+ const body = await localServer.redundancy.listVideos({ target: 'my-videos' })
- return res.body.total
+ return body.total
}
async function getTotalRedundanciesRemoteServer () {
- const res = await listVideoRedundancies({
- url: remoteServer.url,
- accessToken: remoteServer.accessToken,
- target: 'remote-videos'
- })
+ const body = await remoteServer.redundancy.listVideos({ target: 'remote-videos' })
- return res.body.total
+ return body.total
}
before(async function () {
this.timeout(120000)
{
- remoteServer = await flushAndRunServer(1, remoteServerConfig)
+ remoteServer = await createSingleServer(1, remoteServerConfig)
}
{
}
}
}
- localServer = await flushAndRunServer(2, config)
+ localServer = await createSingleServer(2, config)
}
servers = [ remoteServer, localServer ]
// Get the access tokens
await setAccessTokensToServers(servers)
- await uploadVideo(localServer.url, localServer.accessToken, { name: 'video 1 server 2' })
+ await localServer.videos.upload({ attributes: { name: 'video 1 server 2' } })
await waitJobs(servers)
// Server 1 and server 2 follow each other
- await follow(remoteServer.url, [ localServer.url ], remoteServer.accessToken)
+ await remoteServer.follows.follow({ hosts: [ localServer.url ] })
await waitJobs(servers)
- await updateRedundancy(remoteServer.url, remoteServer.accessToken, localServer.host, true)
+ await remoteServer.redundancy.updateRedundancy({ host: localServer.host, redundancyAllowed: true })
await waitJobs(servers)
})
this.timeout(120000)
await waitJobs(servers)
- await waitUntilLog(remoteServer, 'Duplicated ', 5)
+ await remoteServer.servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
{
}
}
await killallServers([ localServer ])
- await reRunServer(localServer, config)
+ await localServer.run(config)
await uploadWrapper('video 2 server 2')
- await waitUntilLog(remoteServer, 'Duplicated ', 10)
+ await remoteServer.servers.waitUntilLog('Duplicated ', 10)
await waitJobs(servers)
{
}
}
await killallServers([ localServer ])
- await reRunServer(localServer, config)
+ await localServer.run(config)
await uploadWrapper('video 3 server 2')
- await waitUntilLog(remoteServer, 'Duplicated ', 15)
+ await remoteServer.servers.waitUntilLog('Duplicated ', 15)
await waitJobs(servers)
{
it('Should have redundancy on server 1 and on server 2 with followings filter now server 2 follows server 1', async function () {
this.timeout(120000)
- await follow(localServer.url, [ remoteServer.url ], localServer.accessToken)
+ await localServer.follows.follow({ hosts: [ remoteServer.url ] })
await waitJobs(servers)
await uploadWrapper('video 4 server 2')
- await waitUntilLog(remoteServer, 'Duplicated ', 20)
+ await remoteServer.servers.waitUntilLog('Duplicated ', 20)
await waitJobs(servers)
{
import * as chai from 'chai'
import { readdir } from 'fs-extra'
import * as magnetUtil from 'magnet-uri'
-import { join } from 'path'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { basename, join } from 'path'
import {
checkSegmentHash,
checkVideoFilesWereRemoved,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getFollowingListPaginationAndSort,
- getVideo,
- getVideoWithToken,
- immutableAssign,
killallServers,
- makeGetRequest,
- removeVideo,
- reRunServer,
+ makeRawRequest,
+ PeerTubeServer,
root,
- ServerInfo,
+ saveVideoInServers,
setAccessTokensToServers,
- unfollow,
- updateVideo,
- uploadVideo,
- viewVideo,
wait,
- waitUntilLog
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+ waitJobs
+} from '@shared/extra-utils'
import {
- addVideoRedundancy,
- listVideoRedundancies,
- removeVideoRedundancy,
- updateRedundancy
-} from '../../../../shared/extra-utils/server/redundancy'
-import { getStats } from '../../../../shared/extra-utils/server/stats'
-import { ActorFollow } from '../../../../shared/models/actors'
-import { VideoRedundancy, VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../../shared/models/redundancy'
-import { ServerStats } from '../../../../shared/models/server/server-stats.model'
-import { VideoDetails, VideoPrivacy } from '../../../../shared/models/videos'
+ HttpStatusCode,
+ VideoDetails,
+ VideoFile,
+ VideoPrivacy,
+ VideoRedundancyStrategy,
+ VideoRedundancyStrategyWithManual
+} from '@shared/models'
const expect = chai.expect
-let servers: ServerInfo[] = []
-let video1Server2UUID: string
-let video1Server2Id: number
+let servers: PeerTubeServer[] = []
+let video1Server2: VideoDetails
-function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: ServerInfo) {
+async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], server: PeerTubeServer) {
const parsed = magnetUtil.decode(file.magnetUri)
for (const ws of baseWebseeds) {
- const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`)
+ const found = parsed.urlList.find(url => url === `${ws}${basename(file.fileUrl)}`)
expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
}
expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
+
+ for (const url of parsed.urlList) {
+ await makeRawRequest(url, HttpStatusCode.OK_200)
+ }
}
-async function flushAndRunServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
+async function createSingleServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
const strategies: any[] = []
if (strategy !== null) {
strategies.push(
- immutableAssign({
+ {
min_lifetime: '1 hour',
strategy: strategy,
- size: '400KB'
- }, additionalParams)
+ size: '400KB',
+
+ ...additionalParams
+ }
)
}
}
}
- servers = await flushAndRunMultipleServers(3, config)
+ servers = await createMultipleServers(3, config)
// Get the access tokens
await setAccessTokensToServers(servers)
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' })
- video1Server2UUID = res.body.video.uuid
- video1Server2Id = res.body.video.id
+ const { id } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
+ video1Server2 = await servers[1].videos.get({ id })
- await viewVideo(servers[1].url, video1Server2UUID)
+ await servers[1].videos.view({ id })
}
await waitJobs(servers)
await waitJobs(servers)
}
+async function ensureSameFilenames (videoUUID: string) {
+ let webtorrentFilenames: string[]
+ let hlsFilenames: string[]
+
+ for (const server of servers) {
+ const video = await server.videos.getWithToken({ id: videoUUID })
+
+ // Ensure we use the same filenames that the origin
+
+ const localWebtorrentFilenames = video.files.map(f => basename(f.fileUrl)).sort()
+ const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
+
+ if (webtorrentFilenames) expect(webtorrentFilenames).to.deep.equal(localWebtorrentFilenames)
+ else webtorrentFilenames = localWebtorrentFilenames
+
+ if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
+ else hlsFilenames = localHLSFilenames
+ }
+
+ return { webtorrentFilenames, hlsFilenames }
+}
+
async function check1WebSeed (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2UUID
+ if (!videoUUID) videoUUID = video1Server2.uuid
const webseeds = [
- `http://localhost:${servers[1].port}/static/webseed/${videoUUID}`
+ `http://localhost:${servers[1].port}/static/webseed/`
]
for (const server of servers) {
// With token to avoid issues with video follow constraints
- const res = await getVideoWithToken(server.url, server.accessToken, videoUUID)
+ const video = await server.videos.getWithToken({ id: videoUUID })
- const video: VideoDetails = res.body
for (const f of video.files) {
- checkMagnetWebseeds(f, webseeds, server)
+ await checkMagnetWebseeds(f, webseeds, server)
}
}
+
+ await ensureSameFilenames(videoUUID)
}
async function check2Webseeds (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2UUID
+ if (!videoUUID) videoUUID = video1Server2.uuid
const webseeds = [
- `http://localhost:${servers[0].port}/static/redundancy/${videoUUID}`,
- `http://localhost:${servers[1].port}/static/webseed/${videoUUID}`
+ `http://localhost:${servers[0].port}/static/redundancy/`,
+ `http://localhost:${servers[1].port}/static/webseed/`
]
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
-
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: videoUUID })
for (const file of video.files) {
- checkMagnetWebseeds(file, webseeds, server)
-
- await makeGetRequest({
- url: servers[0].url,
- statusCodeExpected: HttpStatusCode.OK_200,
- path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`,
- contentType: null
- })
- await makeGetRequest({
- url: servers[1].url,
- statusCodeExpected: HttpStatusCode.OK_200,
- path: `/static/webseed/${videoUUID}-${file.resolution.id}.mp4`,
- contentType: null
- })
+ await checkMagnetWebseeds(file, webseeds, server)
}
}
+ const { webtorrentFilenames } = await ensureSameFilenames(videoUUID)
+
const directories = [
'test' + servers[0].internalServerNumber + '/redundancy',
'test' + servers[1].internalServerNumber + '/videos'
const files = await readdir(join(root(), directory))
expect(files).to.have.length.at.least(4)
- for (const resolution of [ 240, 360, 480, 720 ]) {
- expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined
- }
+ // Ensure we files exist on disk
+ expect(files.find(f => webtorrentFilenames.includes(f))).to.exist
}
}
async function check0PlaylistRedundancies (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2UUID
+ if (!videoUUID) videoUUID = video1Server2.uuid
for (const server of servers) {
// With token to avoid issues with video follow constraints
- const res = await getVideoWithToken(server.url, server.accessToken, videoUUID)
- const video: VideoDetails = res.body
+ const video = await server.videos.getWithToken({ id: videoUUID })
expect(video.streamingPlaylists).to.be.an('array')
expect(video.streamingPlaylists).to.have.lengthOf(1)
expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0)
}
+
+ await ensureSameFilenames(videoUUID)
}
async function check1PlaylistRedundancies (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2UUID
+ if (!videoUUID) videoUUID = video1Server2.uuid
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: videoUUID })
expect(video.streamingPlaylists).to.have.lengthOf(1)
expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(1)
const baseUrlPlaylist = servers[1].url + '/static/streaming-playlists/hls'
const baseUrlSegment = servers[0].url + '/static/redundancy/hls'
- const res = await getVideo(servers[0].url, videoUUID)
- const hlsPlaylist = (res.body as VideoDetails).streamingPlaylists[0]
+ const video = await servers[0].videos.get({ id: videoUUID })
+ const hlsPlaylist = video.streamingPlaylists[0]
for (const resolution of [ 240, 360, 480, 720 ]) {
- await checkSegmentHash(baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist)
+ await checkSegmentHash({ server: servers[1], baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist })
}
+ const { hlsFilenames } = await ensureSameFilenames(videoUUID)
+
const directories = [
'test' + servers[0].internalServerNumber + '/redundancy/hls',
'test' + servers[1].internalServerNumber + '/streaming-playlists/hls'
const files = await readdir(join(root(), directory, videoUUID))
expect(files).to.have.length.at.least(4)
- for (const resolution of [ 240, 360, 480, 720 ]) {
- const filename = `${videoUUID}-${resolution}-fragmented.mp4`
-
- expect(files.find(f => f === filename)).to.not.be.undefined
- }
+ // Ensure we files exist on disk
+ expect(files.find(f => hlsFilenames.includes(f))).to.exist
}
}
statsLength = 2
}
- const res = await getStats(servers[0].url)
- const data: ServerStats = res.body
-
+ const data = await servers[0].stats.get()
expect(data.videosRedundancy).to.have.lengthOf(statsLength)
const stat = data.videosRedundancy[0]
expect(stat.totalVideos).to.equal(0)
}
-async function enableRedundancyOnServer1 () {
- await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, true)
-
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: '-createdAt' })
- const follows: ActorFollow[] = res.body.data
+async function findServerFollows () {
+ const body = await servers[0].follows.getFollowings({ start: 0, count: 5, sort: '-createdAt' })
+ const follows = body.data
const server2 = follows.find(f => f.following.host === `localhost:${servers[1].port}`)
const server3 = follows.find(f => f.following.host === `localhost:${servers[2].port}`)
+ return { server2, server3 }
+}
+
+async function enableRedundancyOnServer1 () {
+ await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
+
+ const { server2, server3 } = await findServerFollows()
+
expect(server3).to.not.be.undefined
expect(server3.following.hostRedundancyAllowed).to.be.false
}
async function disableRedundancyOnServer1 () {
- await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, false)
+ await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: false })
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: '-createdAt' })
- const follows: ActorFollow[] = res.body.data
- const server2 = follows.find(f => f.following.host === `localhost:${servers[1].port}`)
- const server3 = follows.find(f => f.following.host === `localhost:${servers[2].port}`)
+ const { server2, server3 } = await findServerFollows()
expect(server3).to.not.be.undefined
expect(server3.following.hostRedundancyAllowed).to.be.false
before(function () {
this.timeout(120000)
- return flushAndRunServers(strategy)
+ return createSingleServers(strategy)
})
it('Should have 1 webseed on the first video', async function () {
this.timeout(80000)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 5)
+ await servers[0].servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
await check2Webseeds()
await check1WebSeed()
await check0PlaylistRedundancies()
- await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].internalServerNumber, [ 'videos', join('playlists', 'hls') ])
+ await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
})
after(async function () {
before(function () {
this.timeout(120000)
- return flushAndRunServers(strategy)
+ return createSingleServers(strategy)
})
it('Should have 1 webseed on the first video', async function () {
this.timeout(80000)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 5)
+ await servers[0].servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
await check2Webseeds()
it('Should unfollow on server 1 and remove duplicated videos', async function () {
this.timeout(80000)
- await unfollow(servers[0].url, servers[0].accessToken, servers[1])
+ await servers[0].follows.unfollow({ target: servers[1] })
await waitJobs(servers)
await wait(5000)
await check1WebSeed()
await check0PlaylistRedundancies()
- await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].internalServerNumber, [ 'videos' ])
+ await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
})
after(async function () {
before(function () {
this.timeout(120000)
- return flushAndRunServers(strategy, { min_views: 3 })
+ return createSingleServers(strategy, { min_views: 3 })
})
it('Should have 1 webseed on the first video', async function () {
it('Should view 2 times the first video to have > min_views config', async function () {
this.timeout(80000)
- await viewVideo(servers[0].url, video1Server2UUID)
- await viewVideo(servers[2].url, video1Server2UUID)
+ await servers[0].videos.view({ id: video1Server2.uuid })
+ await servers[2].videos.view({ id: video1Server2.uuid })
await wait(10000)
await waitJobs(servers)
this.timeout(80000)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 5)
+ await servers[0].servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
await check2Webseeds()
it('Should remove the video and the redundancy files', async function () {
this.timeout(20000)
- await removeVideo(servers[1].url, servers[1].accessToken, video1Server2UUID)
+ await saveVideoInServers(servers, video1Server2.uuid)
+ await servers[1].videos.remove({ id: video1Server2.uuid })
await waitJobs(servers)
for (const server of servers) {
- await checkVideoFilesWereRemoved(video1Server2UUID, server.internalServerNumber)
+ await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
}
})
before(async function () {
this.timeout(120000)
- await flushAndRunServers(strategy, { min_views: 3 }, false)
+ await createSingleServers(strategy, { min_views: 3 }, false)
})
it('Should have 0 playlist redundancy on the first video', async function () {
it('Should have 1 redundancy on the first video', async function () {
this.timeout(160000)
- await viewVideo(servers[0].url, video1Server2UUID)
- await viewVideo(servers[2].url, video1Server2UUID)
+ await servers[0].videos.view({ id: video1Server2.uuid })
+ await servers[2].videos.view({ id: video1Server2.uuid })
await wait(10000)
await waitJobs(servers)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 1)
+ await servers[0].servers.waitUntilLog('Duplicated ', 1)
await waitJobs(servers)
await check1PlaylistRedundancies()
it('Should remove the video and the redundancy files', async function () {
this.timeout(20000)
- await removeVideo(servers[1].url, servers[1].accessToken, video1Server2UUID)
+ await saveVideoInServers(servers, video1Server2.uuid)
+ await servers[1].videos.remove({ id: video1Server2.uuid })
await waitJobs(servers)
for (const server of servers) {
- await checkVideoFilesWereRemoved(video1Server2UUID, server.internalServerNumber)
+ await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
}
})
before(function () {
this.timeout(120000)
- return flushAndRunServers(null)
+ return createSingleServers(null)
})
it('Should have 1 webseed on the first video', async function () {
})
it('Should create a redundancy on first video', async function () {
- await addVideoRedundancy({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoId: video1Server2Id
- })
+ await servers[0].redundancy.addVideo({ videoId: video1Server2.id })
})
it('Should have 2 webseeds on the first video', async function () {
this.timeout(80000)
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 5)
+ await servers[0].servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
await check2Webseeds()
it('Should manually remove redundancies on server 1 and remove duplicated videos', async function () {
this.timeout(80000)
- const res = await listVideoRedundancies({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- target: 'remote-videos'
- })
+ const body = await servers[0].redundancy.listVideos({ target: 'remote-videos' })
- const videos = res.body.data as VideoRedundancy[]
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
const video = videos[0]
+
for (const r of video.redundancies.files.concat(video.redundancies.streamingPlaylists)) {
- await removeVideoRedundancy({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- redundancyId: r.id
- })
+ await servers[0].redundancy.removeVideo({ redundancyId: r.id })
}
await waitJobs(servers)
await check1WebSeed()
await check0PlaylistRedundancies()
- await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ])
+ await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
})
after(async function () {
describe('Test expiration', function () {
const strategy = 'recently-added'
- async function checkContains (servers: ServerInfo[], str: string) {
+ async function checkContains (servers: PeerTubeServer[], str: string) {
for (const server of servers) {
- const res = await getVideo(server.url, video1Server2UUID)
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: video1Server2.uuid })
for (const f of video.files) {
expect(f.magnetUri).to.contain(str)
}
}
- async function checkNotContains (servers: ServerInfo[], str: string) {
+ async function checkNotContains (servers: PeerTubeServer[], str: string) {
for (const server of servers) {
- const res = await getVideo(server.url, video1Server2UUID)
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: video1Server2.uuid })
for (const f of video.files) {
expect(f.magnetUri).to.not.contain(str)
before(async function () {
this.timeout(120000)
- await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
+ await createSingleServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
await enableRedundancyOnServer1()
})
it('Should stop server 1 and expire video redundancy', async function () {
this.timeout(80000)
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
await wait(15000)
before(async function () {
this.timeout(120000)
- await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
+ await createSingleServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
await enableRedundancyOnServer1()
await waitJobs(servers)
- await waitUntilLog(servers[0], 'Duplicated ', 5)
+ await servers[0].servers.waitUntilLog('Duplicated ', 5)
await waitJobs(servers)
- await check2Webseeds(video1Server2UUID)
- await check1PlaylistRedundancies(video1Server2UUID)
+ await check2Webseeds()
+ await check1PlaylistRedundancies()
await checkStatsWith1Redundancy(strategy)
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE })
- video2Server2UUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE } })
+ video2Server2UUID = uuid
// Wait transcoding before federation
await waitJobs(servers)
- await updateVideo(servers[1].url, servers[1].accessToken, video2Server2UUID, { privacy: VideoPrivacy.PUBLIC })
+ await servers[1].videos.update({ id: video2Server2UUID, attributes: { privacy: VideoPrivacy.PUBLIC } })
})
it('Should cache video 2 webseeds on the first video', async function () {
await wait(1000)
try {
- await check1WebSeed(video1Server2UUID)
- await check0PlaylistRedundancies(video1Server2UUID)
+ await check1WebSeed()
+ await check0PlaylistRedundancies()
await check2Webseeds(video2Server2UUID)
await check1PlaylistRedundancies(video2Server2UUID)
await waitJobs(servers)
- killallServers([ servers[0] ])
- await reRunServer(servers[0], {
+ await killallServers([ servers[0] ])
+ await servers[0].run({
redundancy: {
videos: {
check_interval: '1 second',
await waitJobs(servers)
- await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].internalServerNumber, [ join('redundancy', 'hls') ])
+ await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
- addVideoChannel,
cleanupTests,
- createUser,
- deleteVideoChannel,
- flushAndRunMultipleServers,
- getVideoChannelsList,
- getVideoChannelVideos,
- ServerInfo,
+ createMultipleServers,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers,
- updateMyUser,
- updateVideo,
- updateVideoChannel,
- uploadVideo,
- userLogin,
- wait
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { VideoChannel } from '../../../../shared/models/videos'
-import { searchVideoChannel } from '../../../../shared/extra-utils/search/video-channels'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoChannel } from '@shared/models'
const expect = chai.expect
describe('Test ActivityPub video channels search', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let userServer2Token: string
let videoServer2UUID: string
let channelIdServer2: number
+ let command: SearchCommand
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
{
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: 'user1_server1', password: 'password' })
+ await servers[0].users.create({ username: 'user1_server1', password: 'password' })
const channel = {
name: 'channel1_server1',
displayName: 'Channel 1 server 1'
}
- await addVideoChannel(servers[0].url, servers[0].accessToken, channel)
+ await servers[0].channels.create({ attributes: channel })
}
{
const user = { username: 'user1_server2', password: 'password' }
- await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
- userServer2Token = await userLogin(servers[1], user)
+ await servers[1].users.create({ username: user.username, password: user.password })
+ userServer2Token = await servers[1].login.getAccessToken(user)
const channel = {
name: 'channel1_server2',
displayName: 'Channel 1 server 2'
}
- const resChannel = await addVideoChannel(servers[1].url, userServer2Token, channel)
- channelIdServer2 = resChannel.body.videoChannel.id
+ const created = await servers[1].channels.create({ token: userServer2Token, attributes: channel })
+ channelIdServer2 = created.id
- const res = await uploadVideo(servers[1].url, userServer2Token, { name: 'video 1 server 2', channelId: channelIdServer2 })
- videoServer2UUID = res.body.video.uuid
+ const attributes = { name: 'video 1 server 2', channelId: channelIdServer2 }
+ const { uuid } = await servers[1].videos.upload({ token: userServer2Token, attributes })
+ videoServer2UUID = uuid
}
await waitJobs(servers)
+
+ command = servers[0].search
})
it('Should not find a remote video channel', async function () {
{
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server3'
- const res = await searchVideoChannel(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchChannels({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
// Without token
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
- const res = await searchVideoChannel(servers[0].url, search)
+ const body = await command.searchChannels({ search })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
})
]
for (const search of searches) {
- const res = await searchVideoChannel(servers[0].url, search)
+ const body = await command.searchChannels({ search })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('channel1_server1')
- expect(res.body.data[0].displayName).to.equal('Channel 1 server 1')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('channel1_server1')
+ expect(body.data[0].displayName).to.equal('Channel 1 server 1')
}
})
const search = 'http://localhost:' + servers[0].port + '/c/channel1_server1'
for (const token of [ undefined, servers[0].accessToken ]) {
- const res = await searchVideoChannel(servers[0].url, search, token)
+ const body = await command.searchChannels({ search, token })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('channel1_server1')
- expect(res.body.data[0].displayName).to.equal('Channel 1 server 1')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('channel1_server1')
+ expect(body.data[0].displayName).to.equal('Channel 1 server 1')
}
})
]
for (const search of searches) {
- const res = await searchVideoChannel(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchChannels({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('channel1_server2')
- expect(res.body.data[0].displayName).to.equal('Channel 1 server 2')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('channel1_server2')
+ expect(body.data[0].displayName).to.equal('Channel 1 server 2')
}
})
it('Should not list this remote video channel', async function () {
- const res = await getVideoChannelsList(servers[0].url, 0, 5)
- expect(res.body.total).to.equal(3)
- expect(res.body.data).to.have.lengthOf(3)
- expect(res.body.data[0].name).to.equal('channel1_server1')
- expect(res.body.data[1].name).to.equal('user1_server1_channel')
- expect(res.body.data[2].name).to.equal('root_channel')
+ const body = await servers[0].channels.list()
+ expect(body.total).to.equal(3)
+ expect(body.data).to.have.lengthOf(3)
+ expect(body.data[0].name).to.equal('channel1_server1')
+ expect(body.data[1].name).to.equal('user1_server1_channel')
+ expect(body.data[2].name).to.equal('root_channel')
})
it('Should list video channel videos of server 2 without token', async function () {
await waitJobs(servers)
- const res = await getVideoChannelVideos(servers[0].url, null, 'channel1_server2@localhost:' + servers[1].port, 0, 5)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const { total, data } = await servers[0].videos.listByChannel({
+ token: null,
+ handle: 'channel1_server2@localhost:' + servers[1].port
+ })
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
})
it('Should list video channel videos of server 2 with token', async function () {
- const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, 'channel1_server2@localhost:' + servers[1].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByChannel({
+ handle: 'channel1_server2@localhost:' + servers[1].port
+ })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('video 1 server 2')
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('video 1 server 2')
})
it('Should update video channel of server 2, and refresh it on server 1', async function () {
this.timeout(60000)
- await updateVideoChannel(servers[1].url, userServer2Token, 'channel1_server2', { displayName: 'channel updated' })
- await updateMyUser({ url: servers[1].url, accessToken: userServer2Token, displayName: 'user updated' })
+ await servers[1].channels.update({
+ token: userServer2Token,
+ channelName: 'channel1_server2',
+ attributes: { displayName: 'channel updated' }
+ })
+ await servers[1].users.updateMe({ token: userServer2Token, displayName: 'user updated' })
await waitJobs(servers)
// Expire video channel
await wait(10000)
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
- const res = await searchVideoChannel(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.searchChannels({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const videoChannel: VideoChannel = res.body.data[0]
+ const videoChannel: VideoChannel = body.data[0]
expect(videoChannel.displayName).to.equal('channel updated')
// We don't return the owner account for now
it('Should update and add a video on server 2, and update it on server 1 after a search', async function () {
this.timeout(60000)
- await updateVideo(servers[1].url, userServer2Token, videoServer2UUID, { name: 'video 1 updated' })
- await uploadVideo(servers[1].url, userServer2Token, { name: 'video 2 server 2', channelId: channelIdServer2 })
+ await servers[1].videos.update({ token: userServer2Token, id: videoServer2UUID, attributes: { name: 'video 1 updated' } })
+ await servers[1].videos.upload({ token: userServer2Token, attributes: { name: 'video 2 server 2', channelId: channelIdServer2 } })
await waitJobs(servers)
await wait(10000)
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
- await searchVideoChannel(servers[0].url, search, servers[0].accessToken)
+ await command.searchChannels({ search, token: servers[0].accessToken })
await waitJobs(servers)
- const videoChannelName = 'channel1_server2@localhost:' + servers[1].port
- const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, videoChannelName, 0, 5, '-createdAt')
+ const handle = 'channel1_server2@localhost:' + servers[1].port
+ const { total, data } = await servers[0].videos.listByChannel({ handle, sort: '-createdAt' })
- expect(res.body.total).to.equal(2)
- expect(res.body.data[0].name).to.equal('video 2 server 2')
- expect(res.body.data[1].name).to.equal('video 1 updated')
+ expect(total).to.equal(2)
+ expect(data[0].name).to.equal('video 2 server 2')
+ expect(data[1].name).to.equal('video 1 updated')
})
it('Should delete video channel of server 2, and delete it on server 1', async function () {
this.timeout(60000)
- await deleteVideoChannel(servers[1].url, userServer2Token, 'channel1_server2')
+ await servers[1].channels.delete({ token: userServer2Token, channelName: 'channel1_server2' })
await waitJobs(servers)
// Expire video
await wait(10000)
const search = 'http://localhost:' + servers[1].port + '/video-channels/channel1_server2'
- const res = await searchVideoChannel(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.searchChannels({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
import {
- addVideoInPlaylist,
cleanupTests,
- createVideoPlaylist,
- deleteVideoPlaylist,
- flushAndRunMultipleServers,
- getVideoPlaylistsList,
- searchVideoPlaylists,
- ServerInfo,
+ createMultipleServers,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers,
setDefaultVideoChannel,
- uploadVideoAndGetId,
- wait
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { VideoPlaylist, VideoPlaylistPrivacy } from '../../../../shared/models/videos'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test ActivityPub playlists search', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let playlistServer1UUID: string
let playlistServer2UUID: string
let video2Server2: string
+ let command: SearchCommand
+
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
{
- const video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 1' })).uuid
- const video2 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 2' })).uuid
+ const video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid
+ const video2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).uuid
const attributes = {
displayName: 'playlist 1 on server 1',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].videoChannel.id
+ videoChannelId: servers[0].store.channel.id
}
- const res = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs: attributes })
- playlistServer1UUID = res.body.videoPlaylist.uuid
+ const created = await servers[0].playlists.create({ attributes })
+ playlistServer1UUID = created.uuid
for (const videoId of [ video1, video2 ]) {
- await addVideoInPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistId: playlistServer1UUID,
- elementAttrs: { videoId }
- })
+ await servers[0].playlists.addElement({ playlistId: playlistServer1UUID, attributes: { videoId } })
}
}
{
- const videoId = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 1' })).uuid
- video2Server2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 2' })).uuid
+ const videoId = (await servers[1].videos.quickUpload({ name: 'video 1' })).uuid
+ video2Server2 = (await servers[1].videos.quickUpload({ name: 'video 2' })).uuid
const attributes = {
displayName: 'playlist 1 on server 2',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
}
- const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs: attributes })
- playlistServer2UUID = res.body.videoPlaylist.uuid
-
- await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistServer2UUID,
- elementAttrs: { videoId }
- })
+ const created = await servers[1].playlists.create({ attributes })
+ playlistServer2UUID = created.uuid
+
+ await servers[1].playlists.addElement({ playlistId: playlistServer2UUID, attributes: { videoId } })
}
await waitJobs(servers)
+
+ command = servers[0].search
})
it('Should not find a remote playlist', async function () {
{
const search = 'http://localhost:' + servers[1].port + '/video-playlists/43'
- const res = await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
// Without token
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
- const res = await searchVideoPlaylists(servers[0].url, search)
+ const body = await command.searchPlaylists({ search })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
})
it('Should search a local playlist', async function () {
const search = 'http://localhost:' + servers[0].port + '/video-playlists/' + playlistServer1UUID
- const res = await searchVideoPlaylists(servers[0].url, search)
+ const body = await command.searchPlaylists({ search })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].displayName).to.equal('playlist 1 on server 1')
- expect(res.body.data[0].videosLength).to.equal(2)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
+ expect(body.data[0].videosLength).to.equal(2)
})
it('Should search a local playlist with an alternative URL', async function () {
for (const search of searches) {
for (const token of [ undefined, servers[0].accessToken ]) {
- const res = await searchVideoPlaylists(servers[0].url, search, token)
+ const body = await command.searchPlaylists({ search, token })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].displayName).to.equal('playlist 1 on server 1')
- expect(res.body.data[0].videosLength).to.equal(2)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
+ expect(body.data[0].videosLength).to.equal(2)
}
}
})
]
for (const search of searches) {
- const res = await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].displayName).to.equal('playlist 1 on server 2')
- expect(res.body.data[0].videosLength).to.equal(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('playlist 1 on server 2')
+ expect(body.data[0].videosLength).to.equal(1)
}
})
it('Should not list this remote playlist', async function () {
- const res = await getVideoPlaylistsList(servers[0].url, 0, 10)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].displayName).to.equal('playlist 1 on server 1')
+ const body = await servers[0].playlists.list({ start: 0, count: 10 })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
})
it('Should update the playlist of server 2, and refresh it on server 1', async function () {
this.timeout(60000)
- await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistServer2UUID,
- elementAttrs: { videoId: video2Server2 }
- })
+ await servers[1].playlists.addElement({ playlistId: playlistServer2UUID, attributes: { videoId: video2Server2 } })
await waitJobs(servers)
// Expire playlist
// Will run refresh async
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
- await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
+ await command.searchPlaylists({ search, token: servers[0].accessToken })
// Wait refresh
await wait(5000)
- const res = await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const playlist: VideoPlaylist = res.body.data[0]
+ const playlist = body.data[0]
expect(playlist.videosLength).to.equal(2)
})
it('Should delete playlist of server 2, and delete it on server 1', async function () {
this.timeout(60000)
- await deleteVideoPlaylist(servers[1].url, servers[1].accessToken, playlistServer2UUID)
+ await servers[1].playlists.delete({ playlistId: playlistServer2UUID })
await waitJobs(servers)
// Expiration
// Will run refresh async
const search = 'http://localhost:' + servers[1].port + '/video-playlists/' + playlistServer2UUID
- await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
+ await command.searchPlaylists({ search, token: servers[0].accessToken })
// Wait refresh
await wait(5000)
- const res = await searchVideoPlaylists(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
- addVideoChannel,
cleanupTests,
- flushAndRunMultipleServers,
- getVideosList,
- removeVideo,
- searchVideo,
- searchVideoWithToken,
- ServerInfo,
+ createMultipleServers,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers,
- updateVideo,
- uploadVideo,
- wait
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { Video, VideoPrivacy } from '../../../../shared/models/videos'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test ActivityPub videos search', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoServer1UUID: string
let videoServer2UUID: string
+ let command: SearchCommand
+
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 1 on server 1' })
- videoServer1UUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1 on server 1' } })
+ videoServer1UUID = uuid
}
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 on server 2' })
- videoServer2UUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 1 on server 2' } })
+ videoServer2UUID = uuid
}
await waitJobs(servers)
+
+ command = servers[0].search
})
it('Should not find a remote video', async function () {
{
const search = 'http://localhost:' + servers[1].port + '/videos/watch/43'
- const res = await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchVideos({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
// Without token
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
- const res = await searchVideo(servers[0].url, search)
+ const body = await command.searchVideos({ search })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
})
it('Should search a local video', async function () {
const search = 'http://localhost:' + servers[0].port + '/videos/watch/' + videoServer1UUID
- const res = await searchVideo(servers[0].url, search)
+ const body = await command.searchVideos({ search })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('video 1 on server 1')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('video 1 on server 1')
})
it('Should search a local video with an alternative URL', async function () {
const search = 'http://localhost:' + servers[0].port + '/w/' + videoServer1UUID
- const res1 = await searchVideo(servers[0].url, search)
- const res2 = await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
-
- for (const res of [ res1, res2 ]) {
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('video 1 on server 1')
+ const body1 = await command.searchVideos({ search })
+ const body2 = await command.searchVideos({ search, token: servers[0].accessToken })
+
+ for (const body of [ body1, body2 ]) {
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('video 1 on server 1')
}
})
]
for (const search of searches) {
- const res = await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
+ const body = await command.searchVideos({ search, token: servers[0].accessToken })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('video 1 on server 2')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('video 1 on server 2')
}
})
it('Should not list this remote video', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('video 1 on server 1')
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('video 1 on server 1')
})
it('Should update video of server 2, and refresh it on server 1', async function () {
name: 'super_channel',
displayName: 'super channel'
}
- const resChannel = await addVideoChannel(servers[1].url, servers[1].accessToken, channelAttributes)
- const videoChannelId = resChannel.body.videoChannel.id
+ const created = await servers[1].channels.create({ attributes: channelAttributes })
+ const videoChannelId = created.id
const attributes = {
name: 'updated',
privacy: VideoPrivacy.UNLISTED,
channelId: videoChannelId
}
- await updateVideo(servers[1].url, servers[1].accessToken, videoServer2UUID, attributes)
+ await servers[1].videos.update({ id: videoServer2UUID, attributes })
await waitJobs(servers)
// Expire video
// Will run refresh async
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
- await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
+ await command.searchVideos({ search, token: servers[0].accessToken })
// Wait refresh
await wait(5000)
- const res = await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.searchVideos({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const video: Video = res.body.data[0]
+ const video = body.data[0]
expect(video.name).to.equal('updated')
expect(video.channel.name).to.equal('super_channel')
expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
it('Should delete video of server 2, and delete it on server 1', async function () {
this.timeout(120000)
- await removeVideo(servers[1].url, servers[1].accessToken, videoServer2UUID)
+ await servers[1].videos.remove({ id: videoServer2UUID })
await waitJobs(servers)
// Expire video
// Will run refresh async
const search = 'http://localhost:' + servers[1].port + '/videos/watch/' + videoServer2UUID
- await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
+ await command.searchVideos({ search, token: servers[0].accessToken })
// Wait refresh
await wait(5000)
- const res = await searchVideoWithToken(servers[0].url, search, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.searchVideos({ search, token: servers[0].accessToken })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
-import { searchVideoChannel, advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels'
import {
- addVideoChannel,
cleanupTests,
- createUser,
- flushAndRunServer,
- ServerInfo,
+ createSingleServer,
+ doubleFollow,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers
-} from '../../../../shared/extra-utils'
+} from '@shared/extra-utils'
import { VideoChannel } from '@shared/models'
const expect = chai.expect
describe('Test channels search', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer
+ let remoteServer: PeerTubeServer
+ let command: SearchCommand
before(async function () {
- this.timeout(30000)
+ this.timeout(120000)
- server = await flushAndRunServer(1)
+ const servers = await Promise.all([
+ createSingleServer(1),
+ createSingleServer(2, { transcoding: { enabled: false } })
+ ])
+ server = servers[0]
+ remoteServer = servers[1]
- await setAccessTokensToServers([ server ])
+ await setAccessTokensToServers([ server, remoteServer ])
{
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'user1', password: 'password' })
+ await server.users.create({ username: 'user1' })
const channel = {
name: 'squall_channel',
displayName: 'Squall channel'
}
- await addVideoChannel(server.url, server.accessToken, channel)
+ await server.channels.create({ attributes: channel })
}
+
+ {
+ await remoteServer.users.create({ username: 'user1' })
+ const channel = {
+ name: 'zell_channel',
+ displayName: 'Zell channel'
+ }
+ const { id } = await remoteServer.channels.create({ attributes: channel })
+
+ await remoteServer.videos.upload({ attributes: { channelId: id } })
+ }
+
+ await doubleFollow(server, remoteServer)
+
+ command = server.search
})
it('Should make a simple search and not have results', async function () {
- const res = await searchVideoChannel(server.url, 'abc')
+ const body = await command.searchChannels({ search: 'abc' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should make a search and have results', async function () {
start: 0,
count: 1
}
- const res = await advancedVideoChannelSearch(server.url, search)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.advancedChannelSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const channel: VideoChannel = res.body.data[0]
+ const channel: VideoChannel = body.data[0]
expect(channel.name).to.equal('squall_channel')
expect(channel.displayName).to.equal('Squall channel')
}
count: 1
}
- const res = await advancedVideoChannelSearch(server.url, search)
+ const body = await command.advancedChannelSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(0)
+ }
+ })
+
+ it('Should filter by host', async function () {
+ {
+ const search = { search: 'channel', host: remoteServer.host }
- expect(res.body.total).to.equal(1)
+ const body = await command.advancedChannelSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('Zell channel')
+ }
+
+ {
+ const search = { search: 'Sq', host: server.host }
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.advancedChannelSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('Squall channel')
+ }
+
+ {
+ const search = { search: 'Squall', host: 'example.com' }
+
+ const body = await command.advancedChannelSearch({ search })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+ })
+
+ it('Should filter by names', async function () {
+ {
+ const body = await command.advancedChannelSearch({ search: { handles: [ 'squall_channel', 'zell_channel' ] } })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('Squall channel')
+ }
+
+ {
+ const body = await command.advancedChannelSearch({ search: { handles: [ 'chocobozzz_channel' ] } })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+
+ {
+ const body = await command.advancedChannelSearch({ search: { handles: [ 'squall_channel', 'zell_channel@' + remoteServer.host ] } })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
+ expect(body.data[0].displayName).to.equal('Squall channel')
+ expect(body.data[1].displayName).to.equal('Zell channel')
}
})
after(async function () {
- await cleanupTests([ server ])
+ await cleanupTests([ server, remoteServer ])
})
})
import 'mocha'
import * as chai from 'chai'
-import { advancedVideoChannelSearch, searchVideoChannel } from '@shared/extra-utils/search/video-channels'
-import { Video, VideoChannel, VideoPlaylist, VideoPlaylistPrivacy, VideoPlaylistType, VideosSearchQuery } from '@shared/models'
+import { cleanupTests, createSingleServer, PeerTubeServer, SearchCommand, setAccessTokensToServers } from '@shared/extra-utils'
import {
- advancedVideoPlaylistSearch,
- advancedVideosSearch,
- cleanupTests,
- flushAndRunServer,
- immutableAssign,
- searchVideo,
- searchVideoPlaylists,
- ServerInfo,
- setAccessTokensToServers,
- updateCustomSubConfig,
- uploadVideo
-} from '../../../../shared/extra-utils'
+ BooleanBothQuery,
+ VideoChannelsSearchQuery,
+ VideoPlaylistPrivacy,
+ VideoPlaylistsSearchQuery,
+ VideoPlaylistType,
+ VideosSearchQuery
+} from '@shared/models'
const expect = chai.expect
describe('Test videos search', function () {
- let server: ServerInfo = null
const localVideoName = 'local video' + new Date().toISOString()
+ let server: PeerTubeServer = null
+ let command: SearchCommand
+
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await uploadVideo(server.url, server.accessToken, { name: localVideoName })
+ await server.videos.upload({ attributes: { name: localVideoName } })
+
+ command = server.search
})
describe('Default search', async function () {
it('Should make a local videos search by default', async function () {
this.timeout(10000)
- await updateCustomSubConfig(server.url, server.accessToken, {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: false,
- disableLocalSearch: false
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ search: {
+ searchIndex: {
+ enabled: true,
+ isDefaultSearch: false,
+ disableLocalSearch: false
+ }
}
}
})
- const res = await searchVideo(server.url, 'local video')
+ const body = await command.searchVideos({ search: 'local video' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal(localVideoName)
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal(localVideoName)
})
it('Should make a local channels search by default', async function () {
- const res = await searchVideoChannel(server.url, 'root')
+ const body = await command.searchChannels({ search: 'root' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('root_channel')
- expect(res.body.data[0].host).to.equal('localhost:' + server.port)
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('root_channel')
+ expect(body.data[0].host).to.equal('localhost:' + server.port)
})
it('Should make an index videos search by default', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: true,
- disableLocalSearch: false
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ search: {
+ searchIndex: {
+ enabled: true,
+ isDefaultSearch: true,
+ disableLocalSearch: false
+ }
}
}
})
- const res = await searchVideo(server.url, 'local video')
- expect(res.body.total).to.be.greaterThan(2)
+ const body = await command.searchVideos({ search: 'local video' })
+ expect(body.total).to.be.greaterThan(2)
})
it('Should make an index channels search by default', async function () {
- const res = await searchVideoChannel(server.url, 'root')
- expect(res.body.total).to.be.greaterThan(2)
+ const body = await command.searchChannels({ search: 'root' })
+ expect(body.total).to.be.greaterThan(2)
})
it('Should make an index videos search if local search is disabled', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: false,
- disableLocalSearch: true
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ search: {
+ searchIndex: {
+ enabled: true,
+ isDefaultSearch: false,
+ disableLocalSearch: true
+ }
}
}
})
- const res = await searchVideo(server.url, 'local video')
- expect(res.body.total).to.be.greaterThan(2)
+ const body = await command.searchVideos({ search: 'local video' })
+ expect(body.total).to.be.greaterThan(2)
})
it('Should make an index channels search if local search is disabled', async function () {
- const res = await searchVideoChannel(server.url, 'root')
- expect(res.body.total).to.be.greaterThan(2)
+ const body = await command.searchChannels({ search: 'root' })
+ expect(body.total).to.be.greaterThan(2)
})
})
describe('Videos search', async function () {
+ async function check (search: VideosSearchQuery, exists = true) {
+ const body = await command.advancedVideoSearch({ search })
+
+ if (exists === false) {
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ return
+ }
+
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+
+ const video = body.data[0]
+
+ expect(video.name).to.equal('What is PeerTube?')
+ expect(video.category.label).to.equal('Science & Technology')
+ expect(video.licence.label).to.equal('Attribution - Share Alike')
+ expect(video.privacy.label).to.equal('Public')
+ expect(video.duration).to.equal(113)
+ expect(video.thumbnailUrl.startsWith('https://framatube.org/static/thumbnails')).to.be.true
+
+ expect(video.account.host).to.equal('framatube.org')
+ expect(video.account.name).to.equal('framasoft')
+ expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft')
+ expect(video.account.avatar).to.exist
+
+ expect(video.channel.host).to.equal('framatube.org')
+ expect(video.channel.name).to.equal('bf54d359-cfad-4935-9d45-9d6be93f63e8')
+ expect(video.channel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8')
+ expect(video.channel.avatar).to.exist
+ }
+
+ const baseSearch: VideosSearchQuery = {
+ search: 'what is peertube',
+ start: 0,
+ count: 2,
+ categoryOneOf: [ 15 ],
+ licenceOneOf: [ 2 ],
+ tagsAllOf: [ 'framasoft', 'peertube' ],
+ startDate: '2018-10-01T10:50:46.396Z',
+ endDate: '2018-10-01T10:55:46.396Z'
+ }
+
it('Should make a simple search and not have results', async function () {
- const res = await searchVideo(server.url, 'djidane'.repeat(50))
+ const body = await command.searchVideos({ search: 'djidane'.repeat(50) })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should make a simple search and have results', async function () {
- const res = await searchVideo(server.url, 'What is PeerTube')
+ const body = await command.searchVideos({ search: 'What is PeerTube' })
- expect(res.body.total).to.be.greaterThan(1)
+ expect(body.total).to.be.greaterThan(1)
})
- it('Should make a complex search', async function () {
-
- async function check (search: VideosSearchQuery, exists = true) {
- const res = await advancedVideosSearch(server.url, search)
-
- if (exists === false) {
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- return
- }
-
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
-
- const video: Video = res.body.data[0]
-
- expect(video.name).to.equal('What is PeerTube?')
- expect(video.category.label).to.equal('Science & Technology')
- expect(video.licence.label).to.equal('Attribution - Share Alike')
- expect(video.privacy.label).to.equal('Public')
- expect(video.duration).to.equal(113)
- expect(video.thumbnailUrl.startsWith('https://framatube.org/static/thumbnails')).to.be.true
+ it('Should make a simple search', async function () {
+ await check(baseSearch)
+ })
- expect(video.account.host).to.equal('framatube.org')
- expect(video.account.name).to.equal('framasoft')
- expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft')
- expect(video.account.avatar).to.exist
+ it('Should search by start date', async function () {
+ const search = { ...baseSearch, startDate: '2018-10-01T10:54:46.396Z' }
+ await check(search, false)
+ })
- expect(video.channel.host).to.equal('framatube.org')
- expect(video.channel.name).to.equal('bf54d359-cfad-4935-9d45-9d6be93f63e8')
- expect(video.channel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8')
- expect(video.channel.avatar).to.exist
- }
+ it('Should search by tags', async function () {
+ const search = { ...baseSearch, tagsAllOf: [ 'toto', 'framasoft' ] }
+ await check(search, false)
+ })
- const baseSearch: VideosSearchQuery = {
- search: 'what is peertube',
- start: 0,
- count: 2,
- categoryOneOf: [ 15 ],
- licenceOneOf: [ 2 ],
- tagsAllOf: [ 'framasoft', 'peertube' ],
- startDate: '2018-10-01T10:50:46.396Z',
- endDate: '2018-10-01T10:55:46.396Z'
- }
+ it('Should search by duration', async function () {
+ const search = { ...baseSearch, durationMin: 2000 }
+ await check(search, false)
+ })
+ it('Should search by nsfw attribute', async function () {
{
- await check(baseSearch)
+ const search = { ...baseSearch, nsfw: 'true' as BooleanBothQuery }
+ await check(search, false)
}
{
- const search = immutableAssign(baseSearch, { startDate: '2018-10-01T10:54:46.396Z' })
- await check(search, false)
+ const search = { ...baseSearch, nsfw: 'false' as BooleanBothQuery }
+ await check(search, true)
}
{
- const search = immutableAssign(baseSearch, { tagsAllOf: [ 'toto', 'framasoft' ] })
- await check(search, false)
+ const search = { ...baseSearch, nsfw: 'both' as BooleanBothQuery }
+ await check(search, true)
}
+ })
+ it('Should search by host', async function () {
{
- const search = immutableAssign(baseSearch, { durationMin: 2000 })
+ const search = { ...baseSearch, host: 'example.com' }
await check(search, false)
}
{
- const search = immutableAssign(baseSearch, { nsfw: 'true' })
- await check(search, false)
+ const search = { ...baseSearch, host: 'framatube.org' }
+ await check(search, true)
}
+ })
+
+ it('Should search by uuids', async function () {
+ const goodUUID = '9c9de5e8-0a1e-484a-b099-e80766180a6d'
+ const goodShortUUID = 'kkGMgK9ZtnKfYAgnEtQxbv'
+ const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
+ const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
{
- const search = immutableAssign(baseSearch, { nsfw: 'false' })
- await check(search, true)
+ const uuidsMatrix = [
+ [ goodUUID ],
+ [ goodUUID, badShortUUID ],
+ [ badShortUUID, goodShortUUID ],
+ [ goodUUID, goodShortUUID ]
+ ]
+
+ for (const uuids of uuidsMatrix) {
+ const search = { ...baseSearch, uuids }
+ await check(search, true)
+ }
}
{
- const search = immutableAssign(baseSearch, { nsfw: 'both' })
- await check(search, true)
+ const uuidsMatrix = [
+ [ badUUID ],
+ [ badShortUUID ]
+ ]
+
+ for (const uuids of uuidsMatrix) {
+ const search = { ...baseSearch, uuids }
+ await check(search, false)
+ }
}
})
count: 5
}
- const res = await advancedVideosSearch(server.url, search)
+ const body = await command.advancedVideoSearch({ search })
- expect(res.body.total).to.be.greaterThan(5)
- expect(res.body.data).to.have.lengthOf(5)
+ expect(body.total).to.be.greaterThan(5)
+ expect(body.data).to.have.lengthOf(5)
})
it('Should use the nsfw instance policy as default', async function () {
let nsfwUUID: string
{
- await updateCustomSubConfig(server.url, server.accessToken, { instance: { defaultNSFWPolicy: 'display' } })
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ instance: { defaultNSFWPolicy: 'display' }
+ }
+ })
- const res = await searchVideo(server.url, 'NSFW search index', '-match')
- const video = res.body.data[0] as Video
+ const body = await command.searchVideos({ search: 'NSFW search index', sort: '-match' })
+ expect(body.data).to.have.length.greaterThan(0)
- expect(res.body.data).to.have.length.greaterThan(0)
+ const video = body.data[0]
expect(video.nsfw).to.be.true
nsfwUUID = video.uuid
}
{
- await updateCustomSubConfig(server.url, server.accessToken, { instance: { defaultNSFWPolicy: 'do_not_list' } })
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ instance: { defaultNSFWPolicy: 'do_not_list' }
+ }
+ })
- const res = await searchVideo(server.url, 'NSFW search index', '-match')
+ const body = await command.searchVideos({ search: 'NSFW search index', sort: '-match' })
try {
- expect(res.body.data).to.have.lengthOf(0)
- } catch (err) {
- //
- const video = res.body.data[0] as Video
+ expect(body.data).to.have.lengthOf(0)
+ } catch {
+ const video = body.data[0]
expect(video.uuid).not.equal(nsfwUUID)
}
describe('Channels search', async function () {
- it('Should make a simple search and not have results', async function () {
- const res = await searchVideoChannel(server.url, 'a'.repeat(500))
+ async function check (search: VideoChannelsSearchQuery, exists = true) {
+ const body = await command.advancedChannelSearch({ search })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- const res = await advancedVideoChannelSearch(server.url, { search: 'Framasoft', sort: 'createdAt' })
+ if (exists === false) {
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ return
+ }
- expect(res.body.total).to.be.greaterThan(0)
- expect(res.body.data).to.have.length.greaterThan(0)
+ expect(body.total).to.be.greaterThan(0)
+ expect(body.data).to.have.length.greaterThan(0)
- const videoChannel: VideoChannel = res.body.data[0]
+ const videoChannel = body.data[0]
expect(videoChannel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8')
expect(videoChannel.host).to.equal('framatube.org')
expect(videoChannel.avatar).to.exist
expect(videoChannel.ownerAccount.name).to.equal('framasoft')
expect(videoChannel.ownerAccount.host).to.equal('framatube.org')
expect(videoChannel.ownerAccount.avatar).to.exist
+ }
+
+ it('Should make a simple search and not have results', async function () {
+ const body = await command.searchChannels({ search: 'a'.repeat(500) })
+
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ })
+
+ it('Should make a search and have results', async function () {
+ await check({ search: 'Framasoft', sort: 'createdAt' }, true)
+ })
+
+ it('Should make host search and have appropriate results', async function () {
+ await check({ search: 'Framasoft', host: 'example.com' }, false)
+ await check({ search: 'Framasoft', host: 'framatube.org' }, true)
+ })
+
+ it('Should make handles search and have appropriate results', async function () {
+ await check({ handles: [ 'bf54d359-cfad-4935-9d45-9d6be93f63e8@framatube.org' ] }, true)
+ await check({ handles: [ 'jeanine', 'bf54d359-cfad-4935-9d45-9d6be93f63e8@framatube.org' ] }, true)
+ await check({ handles: [ 'jeanine', 'chocobozzz_channel2@peertube2.cpy.re' ] }, false)
})
it('Should have a correct pagination', async function () {
- const res = await advancedVideoChannelSearch(server.url, { search: 'root', start: 0, count: 2 })
+ const body = await command.advancedChannelSearch({ search: { search: 'root', start: 0, count: 2 } })
- expect(res.body.total).to.be.greaterThan(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.be.greaterThan(2)
+ expect(body.data).to.have.lengthOf(2)
})
})
describe('Playlists search', async function () {
- it('Should make a simple search and not have results', async function () {
- const res = await searchVideoPlaylists(server.url, 'a'.repeat(500))
+ async function check (search: VideoPlaylistsSearchQuery, exists = true) {
+ const body = await command.advancedPlaylistSearch({ search })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- const res = await advancedVideoPlaylistSearch(server.url, { search: 'E2E playlist', sort: '-match' })
+ if (exists === false) {
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ return
+ }
- expect(res.body.total).to.be.greaterThan(0)
- expect(res.body.data).to.have.length.greaterThan(0)
+ expect(body.total).to.be.greaterThan(0)
+ expect(body.data).to.have.length.greaterThan(0)
- const videoPlaylist: VideoPlaylist = res.body.data[0]
+ const videoPlaylist = body.data[0]
expect(videoPlaylist.url).to.equal('https://peertube2.cpy.re/videos/watch/playlist/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a')
expect(videoPlaylist.thumbnailUrl).to.exist
expect(videoPlaylist.videoChannel.name).to.equal('chocobozzz_channel')
expect(videoPlaylist.videoChannel.host).to.equal('peertube2.cpy.re')
expect(videoPlaylist.videoChannel.avatar).to.exist
+ }
+
+ it('Should make a simple search and not have results', async function () {
+ const body = await command.searchPlaylists({ search: 'a'.repeat(500) })
+
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ })
+
+ it('Should make a search and have results', async function () {
+ await check({ search: 'E2E playlist', sort: '-match' }, true)
+ })
+
+ it('Should make host search and have appropriate results', async function () {
+ await check({ search: 'E2E playlist', host: 'example.com' }, false)
+ await check({ search: 'E2E playlist', host: 'peertube2.cpy.re', sort: '-match' }, true)
+ })
+
+ it('Should make a search by uuids and have appropriate results', async function () {
+ const goodUUID = '73804a40-da9a-40c2-b1eb-2c6d9eec8f0a'
+ const goodShortUUID = 'fgei1ws1oa6FCaJ2qZPG29'
+ const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
+ const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
+
+ {
+ const uuidsMatrix = [
+ [ goodUUID ],
+ [ goodUUID, badShortUUID ],
+ [ badShortUUID, goodShortUUID ],
+ [ goodUUID, goodShortUUID ]
+ ]
+
+ for (const uuids of uuidsMatrix) {
+ const search = { search: 'E2E playlist', sort: '-match', uuids }
+ await check(search, true)
+ }
+ }
+
+ {
+ const uuidsMatrix = [
+ [ badUUID ],
+ [ badShortUUID ]
+ ]
+
+ for (const uuids of uuidsMatrix) {
+ const search = { search: 'E2E playlist', sort: '-match', uuids }
+ await check(search, false)
+ }
+ }
})
it('Should have a correct pagination', async function () {
- const res = await advancedVideoChannelSearch(server.url, { search: 'root', start: 0, count: 2 })
+ const body = await command.advancedChannelSearch({ search: { search: 'root', start: 0, count: 2 } })
- expect(res.body.total).to.be.greaterThan(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.be.greaterThan(2)
+ expect(body.data).to.have.lengthOf(2)
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoPlaylist, VideoPlaylistPrivacy } from '@shared/models'
import {
- addVideoInPlaylist,
- advancedVideoPlaylistSearch,
cleanupTests,
- createVideoPlaylist,
- flushAndRunServer,
- searchVideoPlaylists,
- ServerInfo,
+ createSingleServer,
+ doubleFollow,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers,
- setDefaultVideoChannel,
- uploadVideoAndGetId
-} from '../../../../shared/extra-utils'
+ setDefaultVideoChannel
+} from '@shared/extra-utils'
+import { VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test playlists search', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer
+ let remoteServer: PeerTubeServer
+ let command: SearchCommand
+ let playlistUUID: string
+ let playlistShortUUID: string
before(async function () {
- this.timeout(30000)
+ this.timeout(120000)
- server = await flushAndRunServer(1)
+ const servers = await Promise.all([
+ createSingleServer(1),
+ createSingleServer(2, { transcoding: { enabled: false } })
+ ])
+ server = servers[0]
+ remoteServer = servers[1]
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- const videoId = (await uploadVideoAndGetId({ server: server, videoName: 'video' })).uuid
+ await setAccessTokensToServers([ remoteServer, server ])
+ await setDefaultVideoChannel([ remoteServer, server ])
{
+ const videoId = (await server.videos.upload()).uuid
+
const attributes = {
displayName: 'Dr. Kenzo Tenma hospital videos',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: server.store.channel.id
}
- const res = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes })
-
- await addVideoInPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: res.body.videoPlaylist.id,
- elementAttrs: { videoId }
- })
+ const created = await server.playlists.create({ attributes })
+ playlistUUID = created.uuid
+ playlistShortUUID = created.shortUUID
+
+ await server.playlists.addElement({ playlistId: created.id, attributes: { videoId } })
}
{
+ const videoId = (await remoteServer.videos.upload()).uuid
+
const attributes = {
- displayName: 'Johan & Anna Libert musics',
+ displayName: 'Johan & Anna Libert music videos',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: remoteServer.store.channel.id
}
- const res = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes })
-
- await addVideoInPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: res.body.videoPlaylist.id,
- elementAttrs: { videoId }
- })
+ const created = await remoteServer.playlists.create({ attributes })
+
+ await remoteServer.playlists.addElement({ playlistId: created.id, attributes: { videoId } })
}
{
const attributes = {
displayName: 'Inspector Lunge playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: server.store.channel.id
}
- await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes })
+ await server.playlists.create({ attributes })
}
+
+ await doubleFollow(server, remoteServer)
+
+ command = server.search
})
it('Should make a simple search and not have results', async function () {
- const res = await searchVideoPlaylists(server.url, 'abc')
+ const body = await command.searchPlaylists({ search: 'abc' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should make a search and have results', async function () {
start: 0,
count: 1
}
- const res = await advancedVideoPlaylistSearch(server.url, search)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const playlist: VideoPlaylist = res.body.data[0]
+ const playlist = body.data[0]
expect(playlist.displayName).to.equal('Dr. Kenzo Tenma hospital videos')
expect(playlist.url).to.equal(server.url + '/video-playlists/' + playlist.uuid)
}
{
const search = {
- search: 'Anna Livert',
+ search: 'Anna Livert music',
start: 0,
count: 1
}
- const res = await advancedVideoPlaylistSearch(server.url, search)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+
+ const playlist = body.data[0]
+ expect(playlist.displayName).to.equal('Johan & Anna Libert music videos')
+ }
+ })
+
+ it('Should filter by host', async function () {
+ {
+ const search = { search: 'tenma', host: server.host }
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+
+ const playlist = body.data[0]
+ expect(playlist.displayName).to.equal('Dr. Kenzo Tenma hospital videos')
+ }
+
+ {
+ const search = { search: 'Anna', host: 'example.com' }
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+
+ {
+ const search = { search: 'video', host: remoteServer.host }
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+
+ const playlist = body.data[0]
+ expect(playlist.displayName).to.equal('Johan & Anna Libert music videos')
+ }
+ })
+
+ it('Should filter by UUIDs', async function () {
+ for (const uuid of [ playlistUUID, playlistShortUUID ]) {
+ const body = await command.advancedPlaylistSearch({ search: { uuids: [ uuid ] } })
+
+ expect(body.total).to.equal(1)
+ expect(body.data[0].displayName).to.equal('Dr. Kenzo Tenma hospital videos')
+ }
+
+ {
+ const body = await command.advancedPlaylistSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
- const playlist: VideoPlaylist = res.body.data[0]
- expect(playlist.displayName).to.equal('Johan & Anna Libert musics')
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
})
start: 0,
count: 1
}
- const res = await advancedVideoPlaylistSearch(server.url, search)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.advancedPlaylistSearch({ search })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
after(async function () {
- await cleanupTests([ server ])
+ await cleanupTests([ server, remoteServer ])
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoPrivacy } from '@shared/models'
import {
- advancedVideosSearch,
cleanupTests,
- createLive,
- flushAndRunServer,
- immutableAssign,
- searchVideo,
- sendRTMPStreamInVideo,
- ServerInfo,
+ createSingleServer,
+ doubleFollow,
+ PeerTubeServer,
+ SearchCommand,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
- updateCustomSubConfig,
- uploadVideo,
- wait,
- waitUntilLivePublished
-} from '../../../../shared/extra-utils'
-import { createVideoCaption } from '../../../../shared/extra-utils/videos/video-captions'
+ wait
+} from '@shared/extra-utils'
+import { VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test videos search', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer
+ let remoteServer: PeerTubeServer
let startDate: string
let videoUUID: string
+ let videoShortUUID: string
+
+ let command: SearchCommand
before(async function () {
- this.timeout(60000)
+ this.timeout(120000)
- server = await flushAndRunServer(1)
+ const servers = await Promise.all([
+ createSingleServer(1),
+ createSingleServer(2)
+ ])
+ server = servers[0]
+ remoteServer = servers[1]
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
+ await setAccessTokensToServers([ server, remoteServer ])
+ await setDefaultVideoChannel([ server, remoteServer ])
{
const attributes1 = {
nsfw: false,
language: 'fr'
}
- await uploadVideo(server.url, server.accessToken, attributes1)
+ await server.videos.upload({ attributes: attributes1 })
- const attributes2 = immutableAssign(attributes1, { name: attributes1.name + ' - 2', fixture: 'video_short.mp4' })
- await uploadVideo(server.url, server.accessToken, attributes2)
+ const attributes2 = { ...attributes1, name: attributes1.name + ' - 2', fixture: 'video_short.mp4' }
+ await server.videos.upload({ attributes: attributes2 })
{
- const attributes3 = immutableAssign(attributes1, { name: attributes1.name + ' - 3', language: undefined })
- const res = await uploadVideo(server.url, server.accessToken, attributes3)
- const videoId = res.body.video.id
- videoUUID = res.body.video.uuid
-
- await createVideoCaption({
- url: server.url,
- accessToken: server.accessToken,
+ const attributes3 = { ...attributes1, name: attributes1.name + ' - 3', language: undefined }
+ const { id, uuid, shortUUID } = await server.videos.upload({ attributes: attributes3 })
+ videoUUID = uuid
+ videoShortUUID = shortUUID
+
+ await server.captions.add({
language: 'en',
- videoId,
+ videoId: id,
fixture: 'subtitle-good2.vtt',
mimeType: 'application/octet-stream'
})
- await createVideoCaption({
- url: server.url,
- accessToken: server.accessToken,
+ await server.captions.add({
language: 'aa',
- videoId,
+ videoId: id,
fixture: 'subtitle-good2.vtt',
mimeType: 'application/octet-stream'
})
}
- const attributes4 = immutableAssign(attributes1, { name: attributes1.name + ' - 4', language: 'pl', nsfw: true })
- await uploadVideo(server.url, server.accessToken, attributes4)
+ const attributes4 = { ...attributes1, name: attributes1.name + ' - 4', language: 'pl', nsfw: true }
+ await server.videos.upload({ attributes: attributes4 })
await wait(1000)
startDate = new Date().toISOString()
- const attributes5 = immutableAssign(attributes1, { name: attributes1.name + ' - 5', licence: 2, language: undefined })
- await uploadVideo(server.url, server.accessToken, attributes5)
+ const attributes5 = { ...attributes1, name: attributes1.name + ' - 5', licence: 2, language: undefined }
+ await server.videos.upload({ attributes: attributes5 })
- const attributes6 = immutableAssign(attributes1, { name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] })
- await uploadVideo(server.url, server.accessToken, attributes6)
+ const attributes6 = { ...attributes1, name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] }
+ await server.videos.upload({ attributes: attributes6 })
- const attributes7 = immutableAssign(attributes1, {
- name: attributes1.name + ' - 7',
- originallyPublishedAt: '2019-02-12T09:58:08.286Z'
- })
- await uploadVideo(server.url, server.accessToken, attributes7)
+ const attributes7 = { ...attributes1, name: attributes1.name + ' - 7', originallyPublishedAt: '2019-02-12T09:58:08.286Z' }
+ await server.videos.upload({ attributes: attributes7 })
- const attributes8 = immutableAssign(attributes1, { name: attributes1.name + ' - 8', licence: 4 })
- await uploadVideo(server.url, server.accessToken, attributes8)
+ const attributes8 = { ...attributes1, name: attributes1.name + ' - 8', licence: 4 }
+ await server.videos.upload({ attributes: attributes8 })
}
{
licence: 2,
language: 'en'
}
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes: attributes })
- await uploadVideo(server.url, server.accessToken, immutableAssign(attributes, { name: attributes.name + ' duplicate' }))
+ await server.videos.upload({ attributes: { ...attributes, name: attributes.name + ' duplicate' } })
}
{
licence: 3,
language: 'pl'
}
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes: attributes })
}
{
tags: [ 'aaaa', 'bbbb', 'cccc' ],
category: 1
}
- await uploadVideo(server.url, server.accessToken, attributes1)
- await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { category: 2 }))
+ await server.videos.upload({ attributes: attributes1 })
+ await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
- await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'cccc', 'dddd' ] }))
- await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'eeee', 'ffff' ] }))
+ await server.videos.upload({ attributes: { ...attributes1, tags: [ 'cccc', 'dddd' ] } })
+ await server.videos.upload({ attributes: { ...attributes1, tags: [ 'eeee', 'ffff' ] } })
}
{
name: 'aaaa 2',
category: 1
}
- await uploadVideo(server.url, server.accessToken, attributes1)
- await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { category: 2 }))
+ await server.videos.upload({ attributes: attributes1 })
+ await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
+ }
+
+ {
+ await remoteServer.videos.upload({ attributes: { name: 'remote video 1' } })
+ await remoteServer.videos.upload({ attributes: { name: 'remote video 2' } })
}
+
+ await doubleFollow(server, remoteServer)
+
+ command = server.search
})
it('Should make a simple search and not have results', async function () {
- const res = await searchVideo(server.url, 'abc')
+ const body = await command.searchVideos({ search: 'abc' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should make a simple search and have results', async function () {
- const res = await searchVideo(server.url, '4444 5555 duplicate')
+ const body = await command.searchVideos({ search: '4444 5555 duplicate' })
- expect(res.body.total).to.equal(2)
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
// bestmatch
})
it('Should make a search on tags too, and have results', async function () {
- const query = {
+ const search = {
search: 'aaaa',
categoryOneOf: [ 1 ]
}
- const res = await advancedVideosSearch(server.url, query)
+ const body = await command.advancedVideoSearch({ search })
- expect(res.body.total).to.equal(2)
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
// bestmatch
})
it('Should filter on tags without a search', async function () {
- const query = {
+ const search = {
tagsAllOf: [ 'bbbb' ]
}
- const res = await advancedVideosSearch(server.url, query)
+ const body = await command.advancedVideoSearch({ search })
- expect(res.body.total).to.equal(2)
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('9999')
})
it('Should filter on category without a search', async function () {
- const query = {
+ const search = {
categoryOneOf: [ 3 ]
}
- const res = await advancedVideosSearch(server.url, query)
+ const body = await command.advancedVideoSearch({ search: search })
- expect(res.body.total).to.equal(1)
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('6666 7777 8888')
categoryOneOf: [ 1 ],
tagsOneOf: [ 'aAaa', 'ffff' ]
}
- const res1 = await advancedVideosSearch(server.url, query)
- expect(res1.body.total).to.equal(2)
- const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsOneOf: [ 'blabla' ] }))
- expect(res2.body.total).to.equal(0)
+ {
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(2)
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { ...query, tagsOneOf: [ 'blabla' ] } })
+ expect(body.total).to.equal(0)
+ }
})
it('Should search by tags (all of)', async function () {
categoryOneOf: [ 1 ],
tagsAllOf: [ 'CCcc' ]
}
- const res1 = await advancedVideosSearch(server.url, query)
- expect(res1.body.total).to.equal(2)
- const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsAllOf: [ 'blAbla' ] }))
- expect(res2.body.total).to.equal(0)
+ {
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(2)
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'blAbla' ] } })
+ expect(body.total).to.equal(0)
+ }
- const res3 = await advancedVideosSearch(server.url, immutableAssign(query, { tagsAllOf: [ 'bbbb', 'CCCC' ] }))
- expect(res3.body.total).to.equal(1)
+ {
+ const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'bbbb', 'CCCC' ] } })
+ expect(body.total).to.equal(1)
+ }
})
it('Should search by category', async function () {
search: '6666',
categoryOneOf: [ 3 ]
}
- const res1 = await advancedVideosSearch(server.url, query)
- expect(res1.body.total).to.equal(1)
- expect(res1.body.data[0].name).to.equal('6666 7777 8888')
- const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { categoryOneOf: [ 2 ] }))
- expect(res2.body.total).to.equal(0)
+ {
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('6666 7777 8888')
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { ...query, categoryOneOf: [ 2 ] } })
+ expect(body.total).to.equal(0)
+ }
})
it('Should search by licence', async function () {
search: '4444 5555',
licenceOneOf: [ 2 ]
}
- const res1 = await advancedVideosSearch(server.url, query)
- expect(res1.body.total).to.equal(2)
- expect(res1.body.data[0].name).to.equal('3333 4444 5555')
- expect(res1.body.data[1].name).to.equal('3333 4444 5555 duplicate')
- const res2 = await advancedVideosSearch(server.url, immutableAssign(query, { licenceOneOf: [ 3 ] }))
- expect(res2.body.total).to.equal(0)
+ {
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(2)
+ expect(body.data[0].name).to.equal('3333 4444 5555')
+ expect(body.data[1].name).to.equal('3333 4444 5555 duplicate')
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { ...query, licenceOneOf: [ 3 ] } })
+ expect(body.total).to.equal(0)
+ }
})
it('Should search by languages', async function () {
}
{
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(2)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
- expect(res.body.data[1].name).to.equal('1111 2222 3333 - 4')
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(2)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
+ expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
}
{
- const res = await advancedVideosSearch(server.url, immutableAssign(query, { languageOneOf: [ 'pl', 'en', '_unknown' ] }))
- expect(res.body.total).to.equal(3)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
- expect(res.body.data[1].name).to.equal('1111 2222 3333 - 4')
- expect(res.body.data[2].name).to.equal('1111 2222 3333 - 5')
+ const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'pl', 'en', '_unknown' ] } })
+ expect(body.total).to.equal(3)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
+ expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
+ expect(body.data[2].name).to.equal('1111 2222 3333 - 5')
}
{
- const res = await advancedVideosSearch(server.url, immutableAssign(query, { languageOneOf: [ 'eo' ] }))
- expect(res.body.total).to.equal(0)
+ const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'eo' ] } })
+ expect(body.total).to.equal(0)
}
})
startDate
}
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(4)
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(4)
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('1111 2222 3333 - 5')
expect(videos[1].name).to.equal('1111 2222 3333 - 6')
expect(videos[2].name).to.equal('1111 2222 3333 - 7')
licenceOneOf: [ 1, 4 ]
}
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(4)
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(4)
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('1111 2222 3333')
expect(videos[1].name).to.equal('1111 2222 3333 - 6')
expect(videos[2].name).to.equal('1111 2222 3333 - 7')
sort: '-name'
}
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(4)
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(4)
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('1111 2222 3333 - 8')
expect(videos[1].name).to.equal('1111 2222 3333 - 7')
expect(videos[2].name).to.equal('1111 2222 3333 - 6')
count: 1
}
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(4)
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(4)
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('1111 2222 3333 - 8')
})
count: 1
}
- const res = await advancedVideosSearch(server.url, query)
- expect(res.body.total).to.equal(4)
+ const body = await command.advancedVideoSearch({ search: query })
+ expect(body.total).to.equal(4)
- const videos = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('1111 2222 3333')
})
}
{
- const query = immutableAssign(baseQuery, { originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' })
- const res = await advancedVideosSearch(server.url, query)
+ const query = { ...baseQuery, originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
}
{
- const query = immutableAssign(baseQuery, { originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' })
- const res = await advancedVideosSearch(server.url, query)
+ const query = { ...baseQuery, originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
}
{
- const query = immutableAssign(baseQuery, { originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' })
- const res = await advancedVideosSearch(server.url, query)
+ const query = { ...baseQuery, originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(0)
+ expect(body.total).to.equal(0)
}
{
- const query = immutableAssign(baseQuery, { originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' })
- const res = await advancedVideosSearch(server.url, query)
+ const query = { ...baseQuery, originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(0)
+ expect(body.total).to.equal(0)
}
{
- const query = immutableAssign(baseQuery, {
+ const query = {
+ ...baseQuery,
originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
- })
- const res = await advancedVideosSearch(server.url, query)
+ }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(0)
+ expect(body.total).to.equal(0)
}
{
- const query = immutableAssign(baseQuery, {
+ const query = {
+ ...baseQuery,
originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
- })
- const res = await advancedVideosSearch(server.url, query)
+ }
+ const body = await command.advancedVideoSearch({ search: query })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 7')
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
}
})
it('Should search by UUID', async function () {
const search = videoUUID
- const res = await advancedVideosSearch(server.url, { search })
+ const body = await command.advancedVideoSearch({ search: { search } })
+
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
+ })
+
+ it('Should filter by UUIDs', async function () {
+ for (const uuid of [ videoUUID, videoShortUUID ]) {
+ const body = await command.advancedVideoSearch({ search: { uuids: [ uuid ] } })
+
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
+
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+ })
+
+ it('Should search by host', async function () {
+ {
+ const body = await command.advancedVideoSearch({ search: { search: '6666 7777 8888', host: server.host } })
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('6666 7777 8888')
+ }
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3')
+ {
+ const body = await command.advancedVideoSearch({ search: { search: '1111', host: 'example.com' } })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+
+ {
+ const body = await command.advancedVideoSearch({ search: { search: 'remote', host: remoteServer.host } })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
+ expect(body.data[0].name).to.equal('remote video 1')
+ expect(body.data[1].name).to.equal('remote video 2')
+ }
})
it('Should search by live', async function () {
- this.timeout(30000)
+ this.timeout(60000)
{
- const options = {
+ const newConfig = {
search: {
searchIndex: { enabled: false }
},
live: { enabled: true }
}
- await updateCustomSubConfig(server.url, server.accessToken, options)
+ await server.config.updateCustomSubConfig({ newConfig })
}
{
- const res = await advancedVideosSearch(server.url, { isLive: true })
+ const body = await command.advancedVideoSearch({ search: { isLive: true } })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
{
- const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.videoChannel.id }
- const resLive = await createLive(server.url, server.accessToken, liveOptions)
- const liveVideoId = resLive.body.video.uuid
+ const liveCommand = server.live
+
+ const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.store.channel.id }
+ const live = await liveCommand.create({ fields: liveAttributes })
- const command = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId)
- await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
+ const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
+ await liveCommand.waitUntilPublished({ videoId: live.id })
- const res = await advancedVideosSearch(server.url, { isLive: true })
+ const body = await command.advancedVideoSearch({ search: { isLive: true } })
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('live')
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('live')
- await stopFfmpeg(command)
+ await stopFfmpeg(ffmpegCommand)
}
})
import 'mocha'
import * as chai from 'chai'
import {
- acceptFollower,
cleanupTests,
- flushAndRunMultipleServers,
+ createMultipleServers,
MockInstancesIndex,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- unfollow,
- updateCustomSubConfig,
- wait
-} from '../../../../shared/extra-utils/index'
-import { follow, getFollowersListPaginationAndSort, getFollowingListPaginationAndSort } from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { ActorFollow } from '../../../../shared/models/actors'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
-async function checkFollow (follower: ServerInfo, following: ServerInfo, exists: boolean) {
+async function checkFollow (follower: PeerTubeServer, following: PeerTubeServer, exists: boolean) {
{
- const res = await getFollowersListPaginationAndSort({ url: following.url, start: 0, count: 5, sort: '-createdAt' })
- const follows = res.body.data as ActorFollow[]
+ const body = await following.follows.getFollowers({ start: 0, count: 5, sort: '-createdAt' })
+ const follow = body.data.find(f => f.follower.host === follower.host && f.state === 'accepted')
- const follow = follows.find(f => {
- return f.follower.host === follower.host && f.state === 'accepted'
- })
-
- if (exists === true) {
- expect(follow).to.exist
- } else {
- expect(follow).to.be.undefined
- }
+ if (exists === true) expect(follow).to.exist
+ else expect(follow).to.be.undefined
}
{
- const res = await getFollowingListPaginationAndSort({ url: follower.url, start: 0, count: 5, sort: '-createdAt' })
- const follows = res.body.data as ActorFollow[]
-
- const follow = follows.find(f => {
- return f.following.host === following.host && f.state === 'accepted'
- })
+ const body = await follower.follows.getFollowings({ start: 0, count: 5, sort: '-createdAt' })
+ const follow = body.data.find(f => f.following.host === following.host && f.state === 'accepted')
- if (exists === true) {
- expect(follow).to.exist
- } else {
- expect(follow).to.be.undefined
- }
+ if (exists === true) expect(follow).to.exist
+ else expect(follow).to.be.undefined
}
}
-async function server1Follows2 (servers: ServerInfo[]) {
- await follow(servers[0].url, [ servers[1].host ], servers[0].accessToken)
+async function server1Follows2 (servers: PeerTubeServer[]) {
+ await servers[0].follows.follow({ hosts: [ servers[1].host ] })
await waitJobs(servers)
}
-async function resetFollows (servers: ServerInfo[]) {
+async function resetFollows (servers: PeerTubeServer[]) {
try {
- await unfollow(servers[0].url, servers[0].accessToken, servers[1])
- await unfollow(servers[1].url, servers[1].accessToken, servers[0])
+ await servers[0].follows.unfollow({ target: servers[1] })
+ await servers[1].follows.unfollow({ target: servers[0] })
} catch { /* empty */
}
}
describe('Test auto follows', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
}
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config)
+ await servers[1].config.updateCustomSubConfig({ newConfig: config })
await server1Follows2(servers)
}
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config)
+ await servers[1].config.updateCustomSubConfig({ newConfig: config })
await server1Follows2(servers)
await checkFollow(servers[0], servers[1], false)
await checkFollow(servers[1], servers[0], false)
- await acceptFollower(servers[1].url, servers[1].accessToken, 'peertube@' + servers[0].host)
+ await servers[1].follows.acceptFollower({ follower: 'peertube@' + servers[0].host })
await waitJobs(servers)
await checkFollow(servers[0], servers[1], true)
config.followings.instance.autoFollowBack.enabled = false
config.followers.instance.manualApproval = false
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config)
+ await servers[1].config.updateCustomSubConfig({ newConfig: config })
})
})
}
}
}
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
await wait(5000)
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
-import { Video, VideoComment } from '@shared/models'
import {
- addVideoCommentReply,
- addVideoCommentThread,
- bulkRemoveCommentsOf,
+ BulkCommand,
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getVideoCommentThreads,
- getVideosList,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo,
- userLogin,
waitJobs
-} from '../../../../shared/extra-utils/index'
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test bulk actions', function () {
const commentsUser3: { videoId: number, commentId: number }[] = []
- let servers: ServerInfo[] = []
- let user1AccessToken: string
- let user2AccessToken: string
- let user3AccessToken: string
+ let servers: PeerTubeServer[] = []
+ let user1Token: string
+ let user2Token: string
+ let user3Token: string
+
+ let bulkCommand: BulkCommand
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
{
const user = { username: 'user1', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- user1AccessToken = await userLogin(servers[0], user)
+ user1Token = await servers[0].login.getAccessToken(user)
}
{
const user = { username: 'user2', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- user2AccessToken = await userLogin(servers[0], user)
+ user2Token = await servers[0].login.getAccessToken(user)
}
{
const user = { username: 'user3', password: 'password' }
- await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
+ await servers[1].users.create({ username: user.username, password: user.password })
- user3AccessToken = await userLogin(servers[1], user)
+ user3Token = await servers[1].login.getAccessToken(user)
}
await doubleFollow(servers[0], servers[1])
+
+ bulkCommand = new BulkCommand(servers[0])
})
describe('Bulk remove comments', function () {
async function checkInstanceCommentsRemoved () {
{
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data as Video[]
+ const { data } = await servers[0].videos.list()
// Server 1 should not have these comments anymore
- for (const video of videos) {
- const resThreads = await getVideoCommentThreads(servers[0].url, video.id, 0, 10)
- const comments = resThreads.body.data as VideoComment[]
- const comment = comments.find(c => c.text === 'comment by user 3')
+ for (const video of data) {
+ const { data } = await servers[0].comments.listThreads({ videoId: video.id })
+ const comment = data.find(c => c.text === 'comment by user 3')
expect(comment).to.not.exist
}
}
{
- const res = await getVideosList(servers[1].url)
- const videos = res.body.data as Video[]
+ const { data } = await servers[1].videos.list()
// Server 1 should not have these comments on videos of server 1
- for (const video of videos) {
- const resThreads = await getVideoCommentThreads(servers[1].url, video.id, 0, 10)
- const comments = resThreads.body.data as VideoComment[]
- const comment = comments.find(c => c.text === 'comment by user 3')
+ for (const video of data) {
+ const { data } = await servers[1].comments.listThreads({ videoId: video.id })
+ const comment = data.find(c => c.text === 'comment by user 3')
if (video.account.host === 'localhost:' + servers[0].port) {
expect(comment).to.not.exist
before(async function () {
this.timeout(120000)
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 1 server 1' })
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 2 server 1' })
- await uploadVideo(servers[0].url, user1AccessToken, { name: 'video 3 server 1' })
+ await servers[0].videos.upload({ attributes: { name: 'video 1 server 1' } })
+ await servers[0].videos.upload({ attributes: { name: 'video 2 server 1' } })
+ await servers[0].videos.upload({ token: user1Token, attributes: { name: 'video 3 server 1' } })
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' })
+ await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
await waitJobs(servers)
{
- const res = await getVideosList(servers[0].url)
- for (const video of res.body.data) {
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, video.id, 'comment by root server 1')
- await addVideoCommentThread(servers[0].url, user1AccessToken, video.id, 'comment by user 1')
- await addVideoCommentThread(servers[0].url, user2AccessToken, video.id, 'comment by user 2')
+ const { data } = await servers[0].videos.list()
+ for (const video of data) {
+ await servers[0].comments.createThread({ videoId: video.id, text: 'comment by root server 1' })
+ await servers[0].comments.createThread({ token: user1Token, videoId: video.id, text: 'comment by user 1' })
+ await servers[0].comments.createThread({ token: user2Token, videoId: video.id, text: 'comment by user 2' })
}
}
{
- const res = await getVideosList(servers[1].url)
- for (const video of res.body.data) {
- await addVideoCommentThread(servers[1].url, servers[1].accessToken, video.id, 'comment by root server 2')
+ const { data } = await servers[1].videos.list()
- const res = await addVideoCommentThread(servers[1].url, user3AccessToken, video.id, 'comment by user 3')
- commentsUser3.push({ videoId: video.id, commentId: res.body.comment.id })
+ for (const video of data) {
+ await servers[1].comments.createThread({ videoId: video.id, text: 'comment by root server 2' })
+
+ const comment = await servers[1].comments.createThread({ token: user3Token, videoId: video.id, text: 'comment by user 3' })
+ commentsUser3.push({ videoId: video.id, commentId: comment.id })
}
}
it('Should delete comments of an account on my videos', async function () {
this.timeout(60000)
- await bulkRemoveCommentsOf({
- url: servers[0].url,
- token: user1AccessToken,
+ await bulkCommand.removeCommentsOf({
+ token: user1Token,
attributes: {
accountName: 'user2',
scope: 'my-videos'
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- for (const video of res.body.data) {
- const resThreads = await getVideoCommentThreads(server.url, video.id, 0, 10)
- const comments = resThreads.body.data as VideoComment[]
- const comment = comments.find(c => c.text === 'comment by user 2')
+ for (const video of data) {
+ const { data } = await server.comments.listThreads({ videoId: video.id })
+ const comment = data.find(c => c.text === 'comment by user 2')
- if (video.name === 'video 3 server 1') {
- expect(comment).to.not.exist
- } else {
- expect(comment).to.exist
- }
+ if (video.name === 'video 3 server 1') expect(comment).to.not.exist
+ else expect(comment).to.exist
}
}
})
it('Should delete comments of an account on the instance', async function () {
this.timeout(60000)
- await bulkRemoveCommentsOf({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await bulkCommand.removeCommentsOf({
attributes: {
accountName: 'user3@localhost:' + servers[1].port,
scope: 'instance'
this.timeout(60000)
for (const obj of commentsUser3) {
- await addVideoCommentReply(servers[1].url, user3AccessToken, obj.videoId, obj.commentId, 'comment by user 3 bis')
+ await servers[1].comments.addReply({
+ token: user3Token,
+ videoId: obj.videoId,
+ toCommentId: obj.commentId,
+ text: 'comment by user 3 bis'
+ })
}
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
-import { About } from '../../../../shared/models/server/about.model'
-import { CustomConfig } from '../../../../shared/models/server/custom-config.model'
import {
cleanupTests,
- deleteCustomConfig,
- flushAndRunServer,
- getAbout,
- getConfig,
- getCustomConfig,
+ createSingleServer,
killallServers,
makeGetRequest,
parallelTests,
- registerUser,
- reRunServer,
- ServerInfo,
- setAccessTokensToServers,
- updateCustomConfig,
- uploadVideo
-} from '../../../../shared/extra-utils'
-import { ServerConfig } from '../../../../shared/models'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { CustomConfig, HttpStatusCode } from '@shared/models'
const expect = chai.expect
-function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
+function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
expect(data.instance.name).to.equal('PeerTube')
expect(data.instance.shortDescription).to.equal(
'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
}
describe('Test config', function () {
- let server = null
+ let server: PeerTubeServer = null
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
it('Should have a correct config on a server with registration enabled', async function () {
- const res = await getConfig(server.url)
- const data: ServerConfig = res.body
+ const data = await server.config.getConfig()
expect(data.signup.allowed).to.be.true
})
this.timeout(5000)
await Promise.all([
- registerUser(server.url, 'user1', 'super password'),
- registerUser(server.url, 'user2', 'super password'),
- registerUser(server.url, 'user3', 'super password')
+ server.users.register({ username: 'user1' }),
+ server.users.register({ username: 'user2' }),
+ server.users.register({ username: 'user3' })
])
- const res = await getConfig(server.url)
- const data: ServerConfig = res.body
+ const data = await server.config.getConfig()
expect(data.signup.allowed).to.be.false
})
it('Should have the correct video allowed extensions', async function () {
- const res = await getConfig(server.url)
- const data: ServerConfig = res.body
+ const data = await server.config.getConfig()
expect(data.video.file.extensions).to.have.lengthOf(3)
expect(data.video.file.extensions).to.contain('.mp4')
expect(data.video.file.extensions).to.contain('.webm')
expect(data.video.file.extensions).to.contain('.ogv')
- await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
- await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
+ await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
+ await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
expect(data.contactForm.enabled).to.be.true
})
it('Should get the customized configuration', async function () {
- const res = await getCustomConfig(server.url, server.accessToken)
- const data = res.body as CustomConfig
+ const data = await server.config.getCustomConfig()
checkInitialConfig(server, data)
})
}
}
}
- await updateCustomConfig(server.url, server.accessToken, newCustomConfig)
-
- const res = await getCustomConfig(server.url, server.accessToken)
- const data = res.body
+ await server.config.updateCustomConfig({ newCustomConfig })
+ const data = await server.config.getCustomConfig()
checkUpdatedConfig(data)
})
it('Should have the correct updated video allowed extensions', async function () {
this.timeout(10000)
- const res = await getConfig(server.url)
- const data: ServerConfig = res.body
+ const data = await server.config.getConfig()
expect(data.video.file.extensions).to.have.length.above(4)
expect(data.video.file.extensions).to.contain('.mp4')
expect(data.video.file.extensions).to.contain('.ogg')
expect(data.video.file.extensions).to.contain('.flac')
- await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.OK_200)
- await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.OK_200)
+ await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.OK_200 })
+ await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.OK_200 })
})
it('Should have the configuration updated after a restart', async function () {
this.timeout(10000)
- killallServers([ server ])
+ await killallServers([ server ])
- await reRunServer(server)
+ await server.run()
- const res = await getCustomConfig(server.url, server.accessToken)
- const data = res.body
+ const data = await server.config.getCustomConfig()
checkUpdatedConfig(data)
})
it('Should fetch the about information', async function () {
- const res = await getAbout(server.url)
- const data: About = res.body
+ const data = await server.config.getAbout()
expect(data.instance.name).to.equal('PeerTube updated')
expect(data.instance.shortDescription).to.equal('my short description')
it('Should remove the custom configuration', async function () {
this.timeout(10000)
- await deleteCustomConfig(server.url, server.accessToken)
-
- const res = await getCustomConfig(server.url, server.accessToken)
- const data = res.body
+ await server.config.deleteCustomConfig()
+ const data = await server.config.getCustomConfig()
checkInitialConfig(server, data)
})
const res = await makeGetRequest({
url: server.url,
path: '/api/v1/config',
- statusCodeExpected: 200
+ expectedStatus: 200
})
expect(res.headers['x-frame-options']).to.exist
}
- killallServers([ server ])
+ await killallServers([ server ])
const config = {
security: {
frameguard: { enabled: false }
}
}
- server = await reRunServer(server, config)
+ await server.run(config)
{
const res = await makeGetRequest({
url: server.url,
path: '/api/v1/config',
- statusCodeExpected: 200
+ expectedStatus: 200
})
expect(res.headers['x-frame-options']).to.not.exist
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers, wait } from '../../../../shared/extra-utils'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import * as chai from 'chai'
+import {
+ cleanupTests,
+ ContactFormCommand,
+ createSingleServer,
+ MockSmtpServer,
+ PeerTubeServer,
+ setAccessTokensToServers,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
const expect = chai.expect
describe('Test contact form', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
const emails: object[] = []
+ let command: ContactFormCommand
before(async function () {
this.timeout(30000)
port
}
}
- server = await flushAndRunServer(1, overrideConfig)
+ server = await createSingleServer(1, overrideConfig)
await setAccessTokensToServers([ server ])
+
+ command = server.contactForm
})
it('Should send a contact form', async function () {
this.timeout(10000)
- await sendContactForm({
- url: server.url,
+ await command.send({
fromEmail: 'toto@example.com',
body: 'my super message',
subject: 'my subject',
await wait(1000)
- await sendContactForm({
- url: server.url,
+ await command.send({
fromEmail: 'toto@example.com',
body: 'my super message',
subject: 'my subject',
fromName: 'Super toto'
})
- await sendContactForm({
- url: server.url,
+ await command.send({
fromEmail: 'toto@example.com',
body: 'my super message',
fromName: 'Super toto',
it('Should be able to send another contact form after a while', async function () {
await wait(1000)
- await sendContactForm({
- url: server.url,
+ await command.send({
fromEmail: 'toto@example.com',
fromName: 'Super toto',
subject: 'my subject',
import 'mocha'
import * as chai from 'chai'
-import {
- addVideoToBlacklist,
- askResetPassword,
- askSendVerifyEmail,
- blockUser,
- cleanupTests,
- createUser,
- flushAndRunServer,
- removeVideoFromBlacklist,
- reportAbuse,
- resetPassword,
- ServerInfo,
- setAccessTokensToServers,
- unblockUser,
- uploadVideo,
- userLogin,
- verifyEmail
-} from '../../../../shared/extra-utils'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, MockSmtpServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
const expect = chai.expect
describe('Test emails', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userId: number
let userId2: number
let userAccessToken: string
- let videoUUID: string
+ let videoShortUUID: string
let videoId: number
let videoUserUUID: string
port: emailPort
}
}
- server = await flushAndRunServer(1, overrideConfig)
+ server = await createSingleServer(1, overrideConfig)
await setAccessTokensToServers([ server ])
{
- const res = await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userId = res.body.user.id
+ const created = await server.users.create({ username: user.username, password: user.password })
+ userId = created.id
- userAccessToken = await userLogin(server, user)
+ userAccessToken = await server.login.getAccessToken(user)
}
{
- const attributes = {
- name: 'my super user video'
- }
- const res = await uploadVideo(server.url, userAccessToken, attributes)
- videoUserUUID = res.body.video.uuid
+ const attributes = { name: 'my super user video' }
+ const { uuid } = await server.videos.upload({ token: userAccessToken, attributes })
+ videoUserUUID = uuid
}
{
const attributes = {
name: 'my super name'
}
- const res = await uploadVideo(server.url, server.accessToken, attributes)
- videoUUID = res.body.video.uuid
- videoId = res.body.video.id
+ const { shortUUID, id } = await server.videos.upload({ attributes })
+ videoShortUUID = shortUUID
+ videoId = id
}
})
it('Should ask to reset the password', async function () {
this.timeout(10000)
- await askResetPassword(server.url, 'user_1@example.com')
+ await server.users.askResetPassword({ email: 'user_1@example.com' })
await waitJobs(server)
expect(emails).to.have.lengthOf(1)
})
it('Should not reset the password with an invalid verification string', async function () {
- await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', HttpStatusCode.FORBIDDEN_403)
+ await server.users.resetPassword({
+ userId,
+ verificationString: verificationString + 'b',
+ password: 'super_password2',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should reset the password', async function () {
- await resetPassword(server.url, userId, verificationString, 'super_password2')
+ await server.users.resetPassword({ userId, verificationString, password: 'super_password2' })
})
it('Should not reset the password with the same verification string', async function () {
- await resetPassword(server.url, userId, verificationString, 'super_password3', HttpStatusCode.FORBIDDEN_403)
+ await server.users.resetPassword({
+ userId,
+ verificationString,
+ password: 'super_password3',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should login with this new password', async function () {
user.password = 'super_password2'
- await userLogin(server, user)
+ await server.login.getAccessToken(user)
})
})
describe('When creating a user without password', function () {
+
it('Should send a create password email', async function () {
this.timeout(10000)
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: 'create_password',
- password: ''
- })
+ await server.users.create({ username: 'create_password', password: '' })
await waitJobs(server)
expect(emails).to.have.lengthOf(2)
})
it('Should not reset the password with an invalid verification string', async function () {
- await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', HttpStatusCode.FORBIDDEN_403)
+ await server.users.resetPassword({
+ userId: userId2,
+ verificationString: verificationString2 + 'c',
+ password: 'newly_created_password',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should reset the password', async function () {
- await resetPassword(server.url, userId2, verificationString2, 'newly_created_password')
+ await server.users.resetPassword({
+ userId: userId2,
+ verificationString: verificationString2,
+ password: 'newly_created_password'
+ })
})
it('Should login with this new password', async function () {
- await userLogin(server, {
+ await server.login.getAccessToken({
username: 'create_password',
password: 'newly_created_password'
})
})
describe('When creating an abuse', function () {
+
it('Should send the notification email', async function () {
this.timeout(10000)
const reason = 'my super bad reason'
- await reportAbuse({ url: server.url, token: server.accessToken, videoId, reason })
+ await server.abuses.report({ videoId, reason })
await waitJobs(server)
expect(emails).to.have.lengthOf(3)
expect(email['from'][0]['address']).equal('test-admin@localhost')
expect(email['to'][0]['address']).equal('admin' + server.internalServerNumber + '@example.com')
expect(email['subject']).contains('abuse')
- expect(email['text']).contains(videoUUID)
+ expect(email['text']).contains(videoShortUUID)
})
})
this.timeout(10000)
const reason = 'my super bad reason'
- await blockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204, reason)
+ await server.users.banUser({ userId, reason })
await waitJobs(server)
expect(emails).to.have.lengthOf(4)
it('Should send the notification email when unblocking a user', async function () {
this.timeout(10000)
- await unblockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204)
+ await server.users.unbanUser({ userId })
await waitJobs(server)
expect(emails).to.have.lengthOf(5)
this.timeout(10000)
const reason = 'my super reason'
- await addVideoToBlacklist(server.url, server.accessToken, videoUserUUID, reason)
+ await server.blacklist.add({ videoId: videoUserUUID, reason })
await waitJobs(server)
expect(emails).to.have.lengthOf(6)
it('Should send the notification email', async function () {
this.timeout(10000)
- await removeVideoFromBlacklist(server.url, server.accessToken, videoUserUUID)
+ await server.blacklist.remove({ videoId: videoUserUUID })
await waitJobs(server)
expect(emails).to.have.lengthOf(7)
it('Should ask to send the verification email', async function () {
this.timeout(10000)
- await askSendVerifyEmail(server.url, 'user_1@example.com')
+ await server.users.askSendVerifyEmail({ email: 'user_1@example.com' })
await waitJobs(server)
expect(emails).to.have.lengthOf(8)
})
it('Should not verify the email with an invalid verification string', async function () {
- await verifyEmail(server.url, userId, verificationString + 'b', false, HttpStatusCode.FORBIDDEN_403)
+ await server.users.verifyEmail({
+ userId,
+ verificationString: verificationString + 'b',
+ isPendingEmail: false,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should verify the email', async function () {
- await verifyEmail(server.url, userId, verificationString)
+ await server.users.verifyEmail({ userId, verificationString })
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import {
- cleanupTests,
- doubleFollow,
- flushAndRunMultipleServers,
- getAccountVideos,
- getVideo,
- getVideoChannelVideos,
- getVideoWithToken,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '../../../../shared/extra-utils'
-import { unfollow } from '../../../../shared/extra-utils/server/follows'
-import { userLogin } from '../../../../shared/extra-utils/users/login'
-import { createUser } from '../../../../shared/extra-utils/users/users'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-import { PeerTubeProblemDocument, ServerErrorCode } from '@shared/models'
+import * as chai from 'chai'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models'
const expect = chai.expect
describe('Test follow constraints', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let video1UUID: string
let video2UUID: string
- let userAccessToken: string
+ let userToken: string
before(async function () {
this.timeout(90000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video server 1' })
- video1UUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video server 1' } })
+ video1UUID = uuid
}
{
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video server 2' })
- video2UUID = res.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video server 2' } })
+ video2UUID = uuid
}
const user = {
username: 'user1',
password: 'super_password'
}
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(servers[0], user)
+ await servers[0].users.create({ username: user.username, password: user.password })
+ userToken = await servers[0].login.getAccessToken(user)
await doubleFollow(servers[0], servers[1])
})
describe('With an unlogged user', function () {
it('Should get the local video', async function () {
- await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.get({ id: video1UUID })
})
it('Should get the remote video', async function () {
- await getVideo(servers[0].url, video2UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.get({ id: video2UUID })
})
it('Should list local account videos', async function () {
- const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:' + servers[0].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ handle: 'root@localhost:' + servers[0].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote account videos', async function () {
- const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:' + servers[1].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ handle: 'root@localhost:' + servers[1].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list local channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[0].port
- const res = await getVideoChannelVideos(servers[0].url, undefined, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[0].port
+ const { total, data } = await servers[0].videos.listByChannel({ handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[1].port
- const res = await getVideoChannelVideos(servers[0].url, undefined, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[1].port
+ const { total, data } = await servers[0].videos.listByChannel({ handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
})
describe('With a logged user', function () {
it('Should get the local video', async function () {
- await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ token: userToken, id: video1UUID })
})
it('Should get the remote video', async function () {
- await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
})
it('Should list local account videos', async function () {
- const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:' + servers[0].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@localhost:' + servers[0].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote account videos', async function () {
- const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:' + servers[1].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@localhost:' + servers[1].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list local channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[0].port
- const res = await getVideoChannelVideos(servers[0].url, userAccessToken, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[0].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[1].port
- const res = await getVideoChannelVideos(servers[0].url, userAccessToken, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[1].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
})
})
before(async function () {
this.timeout(30000)
- await unfollow(servers[0].url, servers[0].accessToken, servers[1])
+ await servers[0].follows.unfollow({ target: servers[1] })
})
describe('With an unlogged user', function () {
it('Should get the local video', async function () {
- await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.get({ id: video1UUID })
})
it('Should not get the remote video', async function () {
- const res = await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403)
-
- const error = res.body as PeerTubeProblemDocument
+ const body = await servers[0].videos.get({ id: video2UUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
+ const error = body as unknown as PeerTubeProblemDocument
const doc = 'https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/does_not_respect_follow_constraints'
expect(error.type).to.equal(doc)
})
it('Should list local account videos', async function () {
- const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:' + servers[0].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({
+ token: null,
+ handle: 'root@localhost:' + servers[0].port
+ })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should not list remote account videos', async function () {
- const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:' + servers[1].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({
+ token: null,
+ handle: 'root@localhost:' + servers[1].port
+ })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
})
it('Should list local channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[0].port
- const res = await getVideoChannelVideos(servers[0].url, undefined, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[0].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: null, handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should not list remote channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[1].port
- const res = await getVideoChannelVideos(servers[0].url, undefined, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[1].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: null, handle })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
})
})
describe('With a logged user', function () {
it('Should get the local video', async function () {
- await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ token: userToken, id: video1UUID })
})
it('Should get the remote video', async function () {
- await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
})
it('Should list local account videos', async function () {
- const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:' + servers[0].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@localhost:' + servers[0].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote account videos', async function () {
- const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:' + servers[1].port, 0, 5)
+ const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@localhost:' + servers[1].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list local channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[0].port
- const res = await getVideoChannelVideos(servers[0].url, userAccessToken, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[0].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should list remote channel videos', async function () {
- const videoChannelName = 'root_channel@localhost:' + servers[1].port
- const res = await getVideoChannelVideos(servers[0].url, userAccessToken, videoChannelName, 0, 5)
+ const handle = 'root_channel@localhost:' + servers[1].port
+ const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
})
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
- acceptFollower,
cleanupTests,
- flushAndRunMultipleServers,
- ServerInfo,
+ createMultipleServers,
+ FollowsCommand,
+ PeerTubeServer,
setAccessTokensToServers,
- updateCustomSubConfig
-} from '../../../../shared/extra-utils/index'
-import {
- follow,
- getFollowersListPaginationAndSort,
- getFollowingListPaginationAndSort,
- rejectFollower,
- removeFollower
-} from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { ActorFollow } from '../../../../shared/models/actors'
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
-async function checkServer1And2HasFollowers (servers: ServerInfo[], state = 'accepted') {
- {
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(1)
-
- const follow = res.body.data[0] as ActorFollow
- expect(follow.state).to.equal(state)
- expect(follow.follower.url).to.equal('http://localhost:' + servers[0].port + '/accounts/peertube')
- expect(follow.following.url).to.equal('http://localhost:' + servers[1].port + '/accounts/peertube')
- }
+async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
+ const fns = [
+ servers[0].follows.getFollowings.bind(servers[0].follows),
+ servers[1].follows.getFollowers.bind(servers[1].follows)
+ ]
- {
- const res = await getFollowersListPaginationAndSort({ url: servers[1].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(1)
+ for (const fn of fns) {
+ const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
- const follow = res.body.data[0] as ActorFollow
+ const follow = body.data[0]
expect(follow.state).to.equal(state)
expect(follow.follower.url).to.equal('http://localhost:' + servers[0].port + '/accounts/peertube')
expect(follow.following.url).to.equal('http://localhost:' + servers[1].port + '/accounts/peertube')
}
}
-async function checkNoFollowers (servers: ServerInfo[]) {
- {
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(0)
- }
+async function checkNoFollowers (servers: PeerTubeServer[]) {
+ const fns = [
+ servers[0].follows.getFollowings.bind(servers[0].follows),
+ servers[1].follows.getFollowers.bind(servers[1].follows)
+ ]
- {
- const res = await getFollowersListPaginationAndSort({ url: servers[1].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(0)
+ for (const fn of fns) {
+ const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
}
}
describe('Test follows moderation', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
+ let commands: FollowsCommand[]
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
+
+ commands = servers.map(s => s.follows)
})
it('Should have server 1 following server 2', async function () {
this.timeout(30000)
- await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
+ await commands[0].follow({ hosts: [ servers[1].url ] })
await waitJobs(servers)
})
it('Should remove follower on server 2', async function () {
this.timeout(10000)
- await removeFollower(servers[1].url, servers[1].accessToken, servers[0])
+ await commands[1].removeFollower({ follower: servers[0] })
await waitJobs(servers)
})
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig)
+ await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
- await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
+ await commands[0].follow({ hosts: [ servers[1].url ] })
await waitJobs(servers)
await checkNoFollowers(servers)
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig)
+ await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
- await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
+ await commands[0].follow({ hosts: [ servers[1].url ] })
await waitJobs(servers)
await checkServer1And2HasFollowers(servers)
it('Should manually approve followers', async function () {
this.timeout(20000)
- await removeFollower(servers[1].url, servers[1].accessToken, servers[0])
+ await commands[1].removeFollower({ follower: servers[0] })
await waitJobs(servers)
const subConfig = {
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig)
- await updateCustomSubConfig(servers[2].url, servers[2].accessToken, subConfig)
+ await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
+ await servers[2].config.updateCustomSubConfig({ newConfig: subConfig })
- await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
+ await commands[0].follow({ hosts: [ servers[1].url ] })
await waitJobs(servers)
await checkServer1And2HasFollowers(servers, 'pending')
it('Should accept a follower', async function () {
this.timeout(10000)
- await acceptFollower(servers[1].url, servers[1].accessToken, 'peertube@localhost:' + servers[0].port)
+ await commands[1].acceptFollower({ follower: 'peertube@localhost:' + servers[0].port })
await waitJobs(servers)
await checkServer1And2HasFollowers(servers)
it('Should reject another follower', async function () {
this.timeout(20000)
- await follow(servers[0].url, [ servers[2].url ], servers[0].accessToken)
+ await commands[0].follow({ hosts: [ servers[2].url ] })
await waitJobs(servers)
{
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await commands[0].getFollowings({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
}
{
- const res = await getFollowersListPaginationAndSort({ url: servers[1].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(1)
+ const body = await commands[1].getFollowers({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
}
{
- const res = await getFollowersListPaginationAndSort({ url: servers[2].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(1)
+ const body = await commands[2].getFollowers({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
}
- await rejectFollower(servers[2].url, servers[2].accessToken, 'peertube@localhost:' + servers[0].port)
+ await commands[2].rejectFollower({ follower: 'peertube@localhost:' + servers[0].port })
await waitJobs(servers)
await checkServer1And2HasFollowers(servers)
{
- const res = await getFollowersListPaginationAndSort({ url: servers[2].url, start: 0, count: 5, sort: 'createdAt' })
- expect(res.body.total).to.equal(0)
+ const body = await commands[2].getFollowers({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
}
})
import 'mocha'
import * as chai from 'chai'
import {
- addVideoCommentReply,
- addVideoCommentThread,
cleanupTests,
completeVideoCheck,
- createUser,
- createVideoCaption,
+ createMultipleServers,
dateIsValid,
- deleteVideoComment,
expectAccountFollows,
- flushAndRunMultipleServers,
- follow,
- getFollowersListPaginationAndSort,
- getFollowingListPaginationAndSort,
- getVideoCommentThreads,
- getVideosList,
- getVideoThreadComments,
- listVideoCaptions,
- rateVideo,
- ServerInfo,
+ expectChannelsFollows,
+ PeerTubeServer,
setAccessTokensToServers,
testCaptionFile,
- unfollow,
- uploadVideo,
- userLogin,
waitJobs
} from '@shared/extra-utils'
-import { Video, VideoCaption, VideoComment, VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
+import { VideoCreateResult, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test follows', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
})
- it('Should not have followers', async function () {
- for (const server of servers) {
- const res = await getFollowersListPaginationAndSort({ url: server.url, start: 0, count: 5, sort: 'createdAt' })
- const follows = res.body.data
+ describe('Data propagation after follow', function () {
- expect(res.body.total).to.equal(0)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(0)
- }
- })
-
- it('Should not have following', async function () {
- for (const server of servers) {
- const res = await getFollowingListPaginationAndSort({ url: server.url, start: 0, count: 5, sort: 'createdAt' })
- const follows = res.body.data
+ it('Should not have followers/followings', async function () {
+ for (const server of servers) {
+ const bodies = await Promise.all([
+ server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' }),
+ server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
+ ])
- expect(res.body.total).to.equal(0)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(0)
- }
- })
+ for (const body of bodies) {
+ expect(body.total).to.equal(0)
- it('Should have server 1 following server 2 and 3', async function () {
- this.timeout(30000)
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(0)
+ }
+ }
+ })
- await follow(servers[0].url, [ servers[1].url, servers[2].url ], servers[0].accessToken)
+ it('Should have server 1 following root account of server 2 and server 3', async function () {
+ this.timeout(30000)
- await waitJobs(servers)
- })
+ await servers[0].follows.follow({
+ hosts: [ servers[2].url ],
+ handles: [ 'root@' + servers[1].host ]
+ })
- it('Should have 2 followings on server 1', async function () {
- let res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 1, sort: 'createdAt' })
- let follows = res.body.data
+ await waitJobs(servers)
+ })
- expect(res.body.total).to.equal(2)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(1)
+ it('Should have 2 followings on server 1', async function () {
+ const body = await servers[0].follows.getFollowings({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 1, count: 1, sort: 'createdAt' })
- follows = follows.concat(res.body.data)
+ let follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(1)
- const server2Follow = follows.find(f => f.following.host === 'localhost:' + servers[1].port)
- const server3Follow = follows.find(f => f.following.host === 'localhost:' + servers[2].port)
+ const body2 = await servers[0].follows.getFollowings({ start: 1, count: 1, sort: 'createdAt' })
+ follows = follows.concat(body2.data)
- expect(server2Follow).to.not.be.undefined
- expect(server3Follow).to.not.be.undefined
- expect(server2Follow.state).to.equal('accepted')
- expect(server3Follow.state).to.equal('accepted')
- })
+ const server2Follow = follows.find(f => f.following.host === servers[1].host)
+ const server3Follow = follows.find(f => f.following.host === servers[2].host)
- it('Should search/filter followings on server 1', async function () {
- const sort = 'createdAt'
- const start = 0
- const count = 1
- const url = servers[0].url
+ expect(server2Follow).to.not.be.undefined
+ expect(server2Follow.following.name).to.equal('root')
+ expect(server2Follow.state).to.equal('accepted')
- {
- const search = ':' + servers[1].port
+ expect(server3Follow).to.not.be.undefined
+ expect(server3Follow.following.name).to.equal('peertube')
+ expect(server3Follow.state).to.equal('accepted')
+ })
- {
- const res = await getFollowingListPaginationAndSort({ url, start, count, sort, search })
- const follows = res.body.data
+ it('Should have 0 followings on server 2 and 3', async function () {
+ for (const server of [ servers[1], servers[2] ]) {
+ const body = await server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
- expect(res.body.total).to.equal(1)
- expect(follows.length).to.equal(1)
- expect(follows[0].following.host).to.equal('localhost:' + servers[1].port)
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(0)
}
+ })
- {
- const res = await getFollowingListPaginationAndSort({ url, start, count, sort, search, state: 'accepted' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ it('Should have 1 followers on server 3', async function () {
+ const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
+
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(1)
+ expect(follows[0].follower.host).to.equal('localhost:' + servers[0].port)
+ })
+
+ it('Should have 0 followers on server 1 and 2', async function () {
+ for (const server of [ servers[0], servers[1] ]) {
+ const body = await server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
+
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(0)
}
+ })
+
+ it('Should search/filter followings on server 1', async function () {
+ const sort = 'createdAt'
+ const start = 0
+ const count = 1
{
- const res = await getFollowingListPaginationAndSort({ url, start, count, sort, search, state: 'accepted', actorType: 'Person' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const search = ':' + servers[1].port
+
+ {
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search })
+ expect(body.total).to.equal(1)
+
+ const follows = body.data
+ expect(follows).to.have.lengthOf(1)
+ expect(follows[0].following.host).to.equal(servers[1].host)
+ }
+
+ {
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted' })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ }
+
+ {
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ }
+
+ {
+ const body = await servers[0].follows.getFollowings({
+ start,
+ count,
+ sort,
+ search,
+ state: 'accepted',
+ actorType: 'Application'
+ })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+
+ {
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'pending' })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
}
{
- const res = await getFollowingListPaginationAndSort({
- url,
- start,
- count,
- sort,
- search,
- state: 'accepted',
- actorType: 'Application'
- })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'root' })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
}
{
- const res = await getFollowingListPaginationAndSort({ url, start, count, sort, search, state: 'pending' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'bla' })
+ expect(body.total).to.equal(0)
+
+ expect(body.data).to.have.lengthOf(0)
}
- }
+ })
- {
- const res = await getFollowingListPaginationAndSort({ url, start, count, sort, search: 'bla' })
- const follows = res.body.data
+ it('Should search/filter followers on server 2', async function () {
+ const start = 0
+ const count = 5
+ const sort = 'createdAt'
- expect(res.body.total).to.equal(0)
- expect(follows.length).to.equal(0)
- }
- })
+ {
+ const search = servers[0].port + ''
- it('Should have 0 followings on server 2 and 3', async function () {
- for (const server of [ servers[1], servers[2] ]) {
- const res = await getFollowingListPaginationAndSort({ url: server.url, start: 0, count: 5, sort: 'createdAt' })
- const follows = res.body.data
+ {
+ const body = await servers[2].follows.getFollowers({ start, count, sort, search })
+ expect(body.total).to.equal(1)
- expect(res.body.total).to.equal(0)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(0)
- }
- })
+ const follows = body.data
+ expect(follows).to.have.lengthOf(1)
+ expect(follows[0].following.host).to.equal(servers[2].host)
+ }
- it('Should have 1 followers on server 2 and 3', async function () {
- for (const server of [ servers[1], servers[2] ]) {
- const res = await getFollowersListPaginationAndSort({ url: server.url, start: 0, count: 1, sort: 'createdAt' })
+ {
+ const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted' })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ }
- const follows = res.body.data
- expect(res.body.total).to.equal(1)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(1)
- expect(follows[0].follower.host).to.equal('localhost:' + servers[0].port)
- }
- })
+ {
+ const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
- it('Should search/filter followers on server 2', async function () {
- const url = servers[2].url
- const start = 0
- const count = 5
- const sort = 'createdAt'
+ {
+ const body = await servers[2].follows.getFollowers({
+ start,
+ count,
+ sort,
+ search,
+ state: 'accepted',
+ actorType: 'Application'
+ })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
+ }
- {
- const search = servers[0].port + ''
+ {
+ const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'pending' })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
+ }
+ }
{
- const res = await getFollowersListPaginationAndSort({ url, start, count, sort, search })
- const follows = res.body.data
+ const body = await servers[2].follows.getFollowers({ start, count, sort, search: 'bla' })
+ expect(body.total).to.equal(0)
- expect(res.body.total).to.equal(1)
- expect(follows.length).to.equal(1)
- expect(follows[0].following.host).to.equal('localhost:' + servers[2].port)
+ const follows = body.data
+ expect(follows).to.have.lengthOf(0)
}
+ })
- {
- const res = await getFollowersListPaginationAndSort({ url, start, count, sort, search, state: 'accepted' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- }
+ it('Should have the correct follows counts', async function () {
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
+ await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
- {
- const res = await getFollowersListPaginationAndSort({ url, start, count, sort, search, state: 'accepted', actorType: 'Person' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- }
+ // Server 2 and 3 does not know server 1 follow another server (there was not a refresh)
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
- {
- const res = await getFollowersListPaginationAndSort({
- url,
- start,
- count,
- sort,
- search,
- state: 'accepted',
- actorType: 'Application'
- })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
- }
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
+ })
- {
- const res = await getFollowersListPaginationAndSort({ url, start, count, sort, search, state: 'pending' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- }
- }
+ it('Should unfollow server 3 on server 1', async function () {
+ this.timeout(15000)
- {
- const res = await getFollowersListPaginationAndSort({ url, start, count, sort, search: 'bla' })
- const follows = res.body.data
+ await servers[0].follows.unfollow({ target: servers[2] })
- expect(res.body.total).to.equal(0)
- expect(follows.length).to.equal(0)
- }
- })
+ await waitJobs(servers)
+ })
- it('Should have 0 followers on server 1', async function () {
- const res = await getFollowersListPaginationAndSort({ url: servers[0].url, start: 0, count: 5, sort: 'createdAt' })
- const follows = res.body.data
+ it('Should not follow server 3 on server 1 anymore', async function () {
+ const body = await servers[0].follows.getFollowings({ start: 0, count: 2, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
- expect(res.body.total).to.equal(0)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(0)
- })
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(1)
- it('Should have the correct follows counts', async function () {
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[0].port, 0, 2)
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[1].port, 1, 0)
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[2].port, 1, 0)
+ expect(follows[0].following.host).to.equal(servers[1].host)
+ })
- // Server 2 and 3 does not know server 1 follow another server (there was not a refresh)
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0)
+ it('Should not have server 1 as follower on server 3 anymore', async function () {
+ const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0)
- })
+ const follows = body.data
+ expect(follows).to.be.an('array')
+ expect(follows).to.have.lengthOf(0)
+ })
- it('Should unfollow server 3 on server 1', async function () {
- this.timeout(5000)
+ it('Should have the correct follows counts after the unfollow', async function () {
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
- await unfollow(servers[0].url, servers[0].accessToken, servers[2])
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
- await waitJobs(servers)
- })
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 0 })
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
+ })
- it('Should not follow server 3 on server 1 anymore', async function () {
- const res = await getFollowingListPaginationAndSort({ url: servers[0].url, start: 0, count: 2, sort: 'createdAt' })
- const follows = res.body.data
+ it('Should upload a video on server 2 and 3 and propagate only the video of server 2', async function () {
+ this.timeout(60000)
- expect(res.body.total).to.equal(1)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(1)
+ await servers[1].videos.upload({ attributes: { name: 'server2' } })
+ await servers[2].videos.upload({ attributes: { name: 'server3' } })
- expect(follows[0].following.host).to.equal('localhost:' + servers[1].port)
- })
+ await waitJobs(servers)
- it('Should not have server 1 as follower on server 3 anymore', async function () {
- const res = await getFollowersListPaginationAndSort({ url: servers[2].url, start: 0, count: 1, sort: 'createdAt' })
+ {
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('server2')
+ }
- const follows = res.body.data
- expect(res.body.total).to.equal(0)
- expect(follows).to.be.an('array')
- expect(follows.length).to.equal(0)
- })
+ {
+ const { total, data } = await servers[1].videos.list()
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('server2')
+ }
+
+ {
+ const { total, data } = await servers[2].videos.list()
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('server3')
+ }
+ })
- it('Should have the correct follows counts 2', async function () {
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[1].port, 1, 0)
+ it('Should remove account follow', async function () {
+ this.timeout(15000)
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0)
+ await servers[0].follows.unfollow({ target: 'root@' + servers[1].host })
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 0)
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 0, 0)
- })
+ await waitJobs(servers)
+ })
- it('Should upload a video on server 2 and 3 and propagate only the video of server 2', async function () {
- this.timeout(60000)
+ it('Should have removed the account follow', async function () {
+ await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
+ await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'server2' })
- await uploadVideo(servers[2].url, servers[2].accessToken, { name: 'server3' })
+ {
+ const { total, data } = await servers[0].follows.getFollowings()
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
+ }
- await waitJobs(servers)
+ {
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
+ }
+ })
- let res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('server2')
+ it('Should follow a channel', async function () {
+ this.timeout(15000)
- res = await getVideosList(servers[1].url)
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('server2')
+ await servers[0].follows.follow({
+ handles: [ 'root_channel@' + servers[1].host ]
+ })
- res = await getVideosList(servers[2].url)
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('server3')
+ await waitJobs(servers)
+
+ await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
+ await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
+
+ {
+ const { total, data } = await servers[0].follows.getFollowings()
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ }
+
+ {
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
+ }
+ })
})
- describe('Should propagate data on a new following', function () {
- let video4: Video
+ describe('Should propagate data on a new server follow', function () {
+ let video4: VideoCreateResult
before(async function () {
this.timeout(50000)
tags: [ 'tag1', 'tag2', 'tag3' ]
}
- await uploadVideo(servers[2].url, servers[2].accessToken, { name: 'server3-2' })
- await uploadVideo(servers[2].url, servers[2].accessToken, { name: 'server3-3' })
- await uploadVideo(servers[2].url, servers[2].accessToken, video4Attributes)
- await uploadVideo(servers[2].url, servers[2].accessToken, { name: 'server3-5' })
- await uploadVideo(servers[2].url, servers[2].accessToken, { name: 'server3-6' })
+ await servers[2].videos.upload({ attributes: { name: 'server3-2' } })
+ await servers[2].videos.upload({ attributes: { name: 'server3-3' } })
+ video4 = await servers[2].videos.upload({ attributes: video4Attributes })
+ await servers[2].videos.upload({ attributes: { name: 'server3-5' } })
+ await servers[2].videos.upload({ attributes: { name: 'server3-6' } })
{
- const user = { username: 'captain', password: 'password' }
- await createUser({ url: servers[2].url, accessToken: servers[2].accessToken, username: user.username, password: user.password })
- const userAccessToken = await userLogin(servers[2], user)
-
- const resVideos = await getVideosList(servers[2].url)
- video4 = resVideos.body.data.find(v => v.name === 'server3-4')
+ const userAccessToken = await servers[2].users.generateUserAndToken('captain')
- {
- await rateVideo(servers[2].url, servers[2].accessToken, video4.id, 'like')
- await rateVideo(servers[2].url, userAccessToken, video4.id, 'dislike')
- }
-
- {
- {
- const text = 'my super first comment'
- const res = await addVideoCommentThread(servers[2].url, servers[2].accessToken, video4.id, text)
- const threadId = res.body.comment.id
-
- const text1 = 'my super answer to thread 1'
- const childCommentRes = await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, threadId, text1)
- const childCommentId = childCommentRes.body.comment.id
-
- const text2 = 'my super answer to answer of thread 1'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, childCommentId, text2)
-
- const text3 = 'my second answer to thread 1'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, threadId, text3)
- }
+ await servers[2].videos.rate({ id: video4.id, rating: 'like' })
+ await servers[2].videos.rate({ token: userAccessToken, id: video4.id, rating: 'dislike' })
+ }
- {
- const text = 'will be deleted'
- const res = await addVideoCommentThread(servers[2].url, servers[2].accessToken, video4.id, text)
- const threadId = res.body.comment.id
+ {
+ await servers[2].comments.createThread({ videoId: video4.id, text: 'my super first comment' })
- const text1 = 'answer to deleted'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, threadId, text1)
+ await servers[2].comments.addReplyToLastThread({ text: 'my super answer to thread 1' })
+ await servers[2].comments.addReplyToLastReply({ text: 'my super answer to answer of thread 1' })
+ await servers[2].comments.addReplyToLastThread({ text: 'my second answer to thread 1' })
+ }
- const text2 = 'will also be deleted'
- const childCommentRes = await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, threadId, text2)
- const childCommentId = childCommentRes.body.comment.id
+ {
+ const { id: threadId } = await servers[2].comments.createThread({ videoId: video4.id, text: 'will be deleted' })
+ await servers[2].comments.addReplyToLastThread({ text: 'answer to deleted' })
- const text3 = 'my second answer to deleted'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, video4.id, childCommentId, text3)
+ const { id: replyId } = await servers[2].comments.addReplyToLastThread({ text: 'will also be deleted' })
- await deleteVideoComment(servers[2].url, servers[2].accessToken, video4.id, threadId)
- await deleteVideoComment(servers[2].url, servers[2].accessToken, video4.id, childCommentId)
- }
- }
+ await servers[2].comments.addReplyToLastReply({ text: 'my second answer to deleted' })
- {
- await createVideoCaption({
- url: servers[2].url,
- accessToken: servers[2].accessToken,
- language: 'ar',
- videoId: video4.id,
- fixture: 'subtitle-good2.vtt'
- })
- }
+ await servers[2].comments.delete({ videoId: video4.id, commentId: threadId })
+ await servers[2].comments.delete({ videoId: video4.id, commentId: replyId })
}
+ await servers[2].captions.add({
+ language: 'ar',
+ videoId: video4.id,
+ fixture: 'subtitle-good2.vtt'
+ })
+
await waitJobs(servers)
// Server 1 follows server 3
- await follow(servers[0].url, [ servers[2].url ], servers[0].accessToken)
+ await servers[0].follows.follow({ hosts: [ servers[2].url ] })
await waitJobs(servers)
})
- it('Should have the correct follows counts 3', async function () {
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[0].port, 0, 2)
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[1].port, 1, 0)
- await expectAccountFollows(servers[0].url, 'peertube@localhost:' + servers[2].port, 1, 0)
+ it('Should have the correct follows counts', async function () {
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
+ await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
+ await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
+ await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0)
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
+ await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
+ await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 1)
- await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0)
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
+ await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
})
it('Should have propagated videos', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(7)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(7)
- const video2 = res.body.data.find(v => v.name === 'server3-2')
- video4 = res.body.data.find(v => v.name === 'server3-4')
- const video6 = res.body.data.find(v => v.name === 'server3-6')
+ const video2 = data.find(v => v.name === 'server3-2')
+ video4 = data.find(v => v.name === 'server3-4')
+ const video6 = data.find(v => v.name === 'server3-6')
expect(video2).to.not.be.undefined
expect(video4).to.not.be.undefined
support: 'my super support text',
account: {
name: 'root',
- host: 'localhost:' + servers[2].port
+ host: servers[2].host
},
isLocal,
commentsEnabled: true,
}
]
}
- await completeVideoCheck(servers[0].url, video4, checkAttributes)
+ await completeVideoCheck(servers[0], video4, checkAttributes)
})
it('Should have propagated comments', async function () {
- const res1 = await getVideoCommentThreads(servers[0].url, video4.id, 0, 5, 'createdAt')
+ const { total, data } = await servers[0].comments.listThreads({ videoId: video4.id, sort: 'createdAt' })
- expect(res1.body.total).to.equal(2)
- expect(res1.body.data).to.be.an('array')
- expect(res1.body.data).to.have.lengthOf(2)
+ expect(total).to.equal(2)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(2)
{
- const comment: VideoComment = res1.body.data[0]
+ const comment = data[0]
expect(comment.inReplyToCommentId).to.be.null
expect(comment.text).equal('my super first comment')
expect(comment.videoId).to.equal(video4.id)
expect(comment.id).to.equal(comment.threadId)
expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal('localhost:' + servers[2].port)
+ expect(comment.account.host).to.equal(servers[2].host)
expect(comment.totalReplies).to.equal(3)
expect(dateIsValid(comment.createdAt as string)).to.be.true
expect(dateIsValid(comment.updatedAt as string)).to.be.true
const threadId = comment.threadId
- const res2 = await getVideoThreadComments(servers[0].url, video4.id, threadId)
-
- const tree: VideoCommentThreadTree = res2.body
+ const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId })
expect(tree.comment.text).equal('my super first comment')
expect(tree.children).to.have.lengthOf(2)
}
{
- const deletedComment: VideoComment = res1.body.data[1]
+ const deletedComment = data[1]
expect(deletedComment).to.not.be.undefined
expect(deletedComment.isDeleted).to.be.true
expect(deletedComment.deletedAt).to.not.be.null
expect(deletedComment.totalReplies).to.equal(2)
expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
- const res2 = await getVideoThreadComments(servers[0].url, video4.id, deletedComment.threadId)
-
- const tree: VideoCommentThreadTree = res2.body
+ const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId: deletedComment.threadId })
const [ commentRoot, deletedChildRoot ] = tree.children
expect(deletedChildRoot).to.not.be.undefined
})
it('Should have propagated captions', async function () {
- const res = await listVideoCaptions(servers[0].url, video4.id)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await servers[0].captions.list({ videoId: video4.id })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const caption1: VideoCaption = res.body.data[0]
+ const caption1 = body.data[0]
expect(caption1.language.id).to.equal('ar')
expect(caption1.language.label).to.equal('Arabic')
expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/.+-ar.vtt$'))
it('Should unfollow server 3 on server 1 and does not list server 3 videos', async function () {
this.timeout(5000)
- await unfollow(servers[0].url, servers[0].accessToken, servers[2])
+ await servers[0].follows.unfollow({ target: servers[2] })
+
+ await waitJobs(servers)
+
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(1)
+ })
+ })
+
+ describe('Should propagate data on a new channel follow', function () {
+
+ before(async function () {
+ this.timeout(60000)
+
+ await servers[2].videos.upload({ attributes: { name: 'server3-7' } })
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
+ const video = await servers[0].videos.find({ name: 'server3-7' })
+ expect(video).to.not.exist
})
+ it('Should have propagated channel video', async function () {
+ this.timeout(60000)
+
+ await servers[0].follows.follow({ handles: [ 'root_channel@' + servers[2].host ] })
+
+ await waitJobs(servers)
+
+ const video = await servers[0].videos.find({ name: 'server3-7' })
+
+ expect(video).to.exist
+ })
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { JobState, Video } from '../../../../shared/models'
-import { VideoPrivacy } from '../../../../shared/models/videos'
-import { VideoCommentThreadTree } from '../../../../shared/models/videos/comment/video-comment.model'
-
+import * as chai from 'chai'
import {
cleanupTests,
- closeAllSequelize,
+ CommentsCommand,
completeVideoCheck,
- flushAndRunMultipleServers,
- getVideo,
- getVideosList,
- immutableAssign,
+ createMultipleServers,
killallServers,
- reRunServer,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- setActorFollowScores,
- unfollow,
- updateVideo,
- uploadVideo,
- uploadVideoAndGetId,
- wait
-} from '../../../../shared/extra-utils'
-import { follow, getFollowersListPaginationAndSort } from '../../../../shared/extra-utils/server/follows'
-import { getJobsListPaginationAndSort, waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- addVideoCommentReply,
- addVideoCommentThread,
- getVideoCommentThreads,
- getVideoThreadComments
-} from '../../../../shared/extra-utils/videos/video-comments'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode, JobState, VideoCreateResult, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test handle downs', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let threadIdServer1: number
let threadIdServer2: number
let commentIdServer1: number
let commentIdServer2: number
- let missedVideo1: Video
- let missedVideo2: Video
- let unlistedVideo: Video
+ let missedVideo1: VideoCreateResult
+ let missedVideo2: VideoCreateResult
+ let unlistedVideo: VideoCreateResult
const videoIdsServer1: string[] = []
fixture: 'video_short1.webm'
}
- const unlistedVideoAttributes = immutableAssign(videoAttributes, {
- privacy: VideoPrivacy.UNLISTED
- })
+ const unlistedVideoAttributes = { ...videoAttributes, privacy: VideoPrivacy.UNLISTED }
let checkAttributes: any
let unlistedCheckAttributes: any
+ let commentCommands: CommentsCommand[]
+
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
+ commentCommands = servers.map(s => s.comments)
checkAttributes = {
name: 'my super name for server 1',
}
]
}
- unlistedCheckAttributes = immutableAssign(checkAttributes, {
- privacy: VideoPrivacy.UNLISTED
- })
+ unlistedCheckAttributes = { ...checkAttributes, privacy: VideoPrivacy.UNLISTED }
// Get the access tokens
await setAccessTokensToServers(servers)
this.timeout(240000)
// Server 2 and 3 follow server 1
- await follow(servers[1].url, [ servers[0].url ], servers[1].accessToken)
- await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
+ await servers[1].follows.follow({ hosts: [ servers[0].url ] })
+ await servers[2].follows.follow({ hosts: [ servers[0].url ] })
await waitJobs(servers)
// Upload a video to server 1
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ await servers[0].videos.upload({ attributes: videoAttributes })
await waitJobs(servers)
// And check all servers have this video
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
+ const { data } = await server.videos.list()
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
}
// Kill server 2
- killallServers([ servers[1] ])
+ await killallServers([ servers[1] ])
// Remove server 2 follower
for (let i = 0; i < 10; i++) {
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ await servers[0].videos.upload({ attributes: videoAttributes })
}
await waitJobs([ servers[0], servers[2] ])
// Kill server 3
- killallServers([ servers[2] ])
+ await killallServers([ servers[2] ])
- const resLastVideo1 = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- missedVideo1 = resLastVideo1.body.video
+ missedVideo1 = await servers[0].videos.upload({ attributes: videoAttributes })
- const resLastVideo2 = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- missedVideo2 = resLastVideo2.body.video
+ missedVideo2 = await servers[0].videos.upload({ attributes: videoAttributes })
// Unlisted video
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, unlistedVideoAttributes)
- unlistedVideo = resVideo.body.video
+ unlistedVideo = await servers[0].videos.upload({ attributes: unlistedVideoAttributes })
// Add comments to video 2
{
const text = 'thread 1'
- let resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, missedVideo2.uuid, text)
- let comment = resComment.body.comment
+ let comment = await commentCommands[0].createThread({ videoId: missedVideo2.uuid, text })
threadIdServer1 = comment.id
- resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, comment.id, 'comment 1-1')
- comment = resComment.body.comment
+ comment = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-1' })
- resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, comment.id, 'comment 1-2')
- commentIdServer1 = resComment.body.comment.id
+ const created = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-2' })
+ commentIdServer1 = created.id
}
await waitJobs(servers[0])
await wait(11000)
// Only server 3 is still a follower of server 1
- const res = await getFollowersListPaginationAndSort({ url: servers[0].url, start: 0, count: 2, sort: 'createdAt' })
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].follower.host).to.equal('localhost:' + servers[2].port)
+ const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].follower.host).to.equal('localhost:' + servers[2].port)
})
it('Should not have pending/processing jobs anymore', async function () {
const states: JobState[] = [ 'waiting', 'active' ]
for (const state of states) {
- const res = await getJobsListPaginationAndSort({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ const body = await servers[0].jobs.getJobsList({
state: state,
start: 0,
count: 50,
sort: '-createdAt'
})
- expect(res.body.data).to.have.length(0)
+ expect(body.data).to.have.length(0)
}
})
it('Should re-follow server 1', async function () {
this.timeout(35000)
- await reRunServer(servers[1])
- await reRunServer(servers[2])
+ await servers[1].run()
+ await servers[2].run()
- await unfollow(servers[1].url, servers[1].accessToken, servers[0])
+ await servers[1].follows.unfollow({ target: servers[0] })
await waitJobs(servers)
- await follow(servers[1].url, [ servers[0].url ], servers[1].accessToken)
+ await servers[1].follows.follow({ hosts: [ servers[0].url ] })
await waitJobs(servers)
- const res = await getFollowersListPaginationAndSort({ url: servers[0].url, start: 0, count: 2, sort: 'createdAt' })
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(2)
})
it('Should send an update to server 3, and automatically fetch the video', async function () {
this.timeout(15000)
- const res1 = await getVideosList(servers[2].url)
- expect(res1.body.data).to.be.an('array')
- expect(res1.body.data).to.have.lengthOf(11)
+ {
+ const { data } = await servers[2].videos.list()
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(11)
+ }
- await updateVideo(servers[0].url, servers[0].accessToken, missedVideo1.uuid, {})
- await updateVideo(servers[0].url, servers[0].accessToken, unlistedVideo.uuid, {})
+ await servers[0].videos.update({ id: missedVideo1.uuid })
+ await servers[0].videos.update({ id: unlistedVideo.uuid })
await waitJobs(servers)
- const res = await getVideosList(servers[2].url)
- expect(res.body.data).to.be.an('array')
- // 1 video is unlisted
- expect(res.body.data).to.have.lengthOf(12)
+ {
+ const { data } = await servers[2].videos.list()
+ expect(data).to.be.an('array')
+ // 1 video is unlisted
+ expect(data).to.have.lengthOf(12)
+ }
// Check unlisted video
- const resVideo = await getVideo(servers[2].url, unlistedVideo.uuid)
- expect(resVideo.body).not.to.be.undefined
-
- await completeVideoCheck(servers[2].url, resVideo.body, unlistedCheckAttributes)
+ const video = await servers[2].videos.get({ id: unlistedVideo.uuid })
+ await completeVideoCheck(servers[2], video, unlistedCheckAttributes)
})
it('Should send comments on a video to server 3, and automatically fetch the video', async function () {
this.timeout(25000)
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, commentIdServer1, 'comment 1-3')
+ await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer1, text: 'comment 1-3' })
await waitJobs(servers)
- const resVideo = await getVideo(servers[2].url, missedVideo2.uuid)
- expect(resVideo.body).not.to.be.undefined
+ await servers[2].videos.get({ id: missedVideo2.uuid })
{
- let resComment = await getVideoCommentThreads(servers[2].url, missedVideo2.uuid, 0, 5)
- expect(resComment.body.data).to.be.an('array')
- expect(resComment.body.data).to.have.lengthOf(1)
-
- threadIdServer2 = resComment.body.data[0].id
+ const { data } = await servers[2].comments.listThreads({ videoId: missedVideo2.uuid })
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
- resComment = await getVideoThreadComments(servers[2].url, missedVideo2.uuid, threadIdServer2)
+ threadIdServer2 = data[0].id
- const tree: VideoCommentThreadTree = resComment.body
+ const tree = await servers[2].comments.getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer2 })
expect(tree.comment.text).equal('thread 1')
expect(tree.children).to.have.lengthOf(1)
it('Should correctly reply to the comment', async function () {
this.timeout(15000)
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, missedVideo2.uuid, commentIdServer2, 'comment 1-4')
+ await servers[2].comments.addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer2, text: 'comment 1-4' })
await waitJobs(servers)
- {
- const resComment = await getVideoThreadComments(servers[0].url, missedVideo2.uuid, threadIdServer1)
+ const tree = await commentCommands[0].getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer1 })
- const tree: VideoCommentThreadTree = resComment.body
- expect(tree.comment.text).equal('thread 1')
- expect(tree.children).to.have.lengthOf(1)
+ expect(tree.comment.text).equal('thread 1')
+ expect(tree.children).to.have.lengthOf(1)
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('comment 1-1')
- expect(firstChild.children).to.have.lengthOf(1)
+ const firstChild = tree.children[0]
+ expect(firstChild.comment.text).to.equal('comment 1-1')
+ expect(firstChild.children).to.have.lengthOf(1)
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
- expect(childOfFirstChild.children).to.have.lengthOf(1)
+ const childOfFirstChild = firstChild.children[0]
+ expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
+ expect(childOfFirstChild.children).to.have.lengthOf(1)
- const childOfChildFirstChild = childOfFirstChild.children[0]
- expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
- expect(childOfChildFirstChild.children).to.have.lengthOf(1)
+ const childOfChildFirstChild = childOfFirstChild.children[0]
+ expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
+ expect(childOfChildFirstChild.children).to.have.lengthOf(1)
- const childOfChildOfChildOfFirstChild = childOfChildFirstChild.children[0]
- expect(childOfChildOfChildOfFirstChild.comment.text).to.equal('comment 1-4')
- expect(childOfChildOfChildOfFirstChild.children).to.have.lengthOf(0)
- }
+ const childOfChildOfChildOfFirstChild = childOfChildFirstChild.children[0]
+ expect(childOfChildOfChildOfFirstChild.comment.text).to.equal('comment 1-4')
+ expect(childOfChildOfChildOfFirstChild.children).to.have.lengthOf(0)
})
it('Should upload many videos on server 1', async function () {
this.timeout(120000)
for (let i = 0; i < 10; i++) {
- const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video ' + i })).uuid
+ const uuid = (await servers[0].videos.quickUpload({ name: 'video ' + i })).uuid
videoIdsServer1.push(uuid)
}
await waitJobs(servers)
for (const id of videoIdsServer1) {
- await getVideo(servers[1].url, id)
+ await servers[1].videos.get({ id })
}
await waitJobs(servers)
- await setActorFollowScores(servers[1].internalServerNumber, 20)
+ await servers[1].sql.setActorFollowScores(20)
// Wait video expiration
await wait(11000)
// Refresh video -> score + 10 = 30
- await getVideo(servers[1].url, videoIdsServer1[0])
+ await servers[1].videos.get({ id: videoIdsServer1[0] })
await waitJobs(servers)
})
it('Should remove followings that are down', async function () {
this.timeout(120000)
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
// Wait video expiration
await wait(11000)
for (let i = 0; i < 5; i++) {
try {
- await getVideo(servers[1].url, videoIdsServer1[i])
+ await servers[1].videos.get({ id: videoIdsServer1[i] })
await waitJobs([ servers[1] ])
await wait(1500)
} catch {}
}
for (const id of videoIdsServer1) {
- await getVideo(servers[1].url, id, HttpStatusCode.FORBIDDEN_403)
+ await servers[1].videos.get({ id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
}
})
after(async function () {
- await closeAllSequelize([ servers[1] ])
-
await cleanupTests(servers)
})
})
import 'mocha'
import * as chai from 'chai'
-import { HttpStatusCode } from '@shared/core-utils'
-import { CustomPage, ServerConfig } from '@shared/models'
+import { HttpStatusCode } from '@shared/models'
import {
cleanupTests,
- flushAndRunServer,
- getConfig,
- getInstanceHomepage,
+ createSingleServer,
+ CustomPagesCommand,
killallServers,
- reRunServer,
- ServerInfo,
- setAccessTokensToServers,
- updateInstanceHomepage
+ PeerTubeServer,
+ setAccessTokensToServers
} from '../../../../shared/extra-utils/index'
const expect = chai.expect
-async function getHomepageState (server: ServerInfo) {
- const res = await getConfig(server.url)
+async function getHomepageState (server: PeerTubeServer) {
+ const config = await server.config.getConfig()
- const config = res.body as ServerConfig
return config.homepage.enabled
}
describe('Test instance homepage actions', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
+ let command: CustomPagesCommand
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
+
+ command = server.customPage
})
it('Should not have a homepage', async function () {
const state = await getHomepageState(server)
expect(state).to.be.false
- await getInstanceHomepage(server.url, HttpStatusCode.NOT_FOUND_404)
+ await command.getInstanceHomepage({ expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should set a homepage', async function () {
- await updateInstanceHomepage(server.url, server.accessToken, '<picsou-magazine></picsou-magazine>')
+ await command.updateInstanceHomepage({ content: '<picsou-magazine></picsou-magazine>' })
- const res = await getInstanceHomepage(server.url)
- const page: CustomPage = res.body
+ const page = await command.getInstanceHomepage()
expect(page.content).to.equal('<picsou-magazine></picsou-magazine>')
const state = await getHomepageState(server)
it('Should have the same homepage after a restart', async function () {
this.timeout(30000)
- killallServers([ server ])
+ await killallServers([ server ])
- await reRunServer(server)
+ await server.run()
- const res = await getInstanceHomepage(server.url)
- const page: CustomPage = res.body
+ const page = await command.getInstanceHomepage()
expect(page.content).to.equal('<picsou-magazine></picsou-magazine>')
const state = await getHomepageState(server)
})
it('Should empty the homepage', async function () {
- await updateInstanceHomepage(server.url, server.accessToken, '')
+ await command.updateInstanceHomepage({ content: '' })
- const res = await getInstanceHomepage(server.url)
- const page: CustomPage = res.body
+ const page = await command.getInstanceHomepage()
expect(page.content).to.be.empty
const state = await getHomepageState(server)
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { cleanupTests, ServerInfo, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
-import { getJobsList, getJobsListPaginationAndSort, waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { flushAndRunMultipleServers } from '../../../../shared/extra-utils/server/servers'
-import { uploadVideo } from '../../../../shared/extra-utils/videos/videos'
-import { dateIsValid } from '../../../../shared/extra-utils/miscs/miscs'
-import { Job } from '../../../../shared/models/server'
+import * as chai from 'chai'
+import {
+ cleanupTests,
+ createMultipleServers,
+ dateIsValid,
+ doubleFollow,
+ PeerTubeServer,
+ setAccessTokensToServers,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test jobs', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
})
it('Should create some jobs', async function () {
- this.timeout(60000)
+ this.timeout(120000)
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video1' })
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video2' })
+ await servers[1].videos.upload({ attributes: { name: 'video1' } })
+ await servers[1].videos.upload({ attributes: { name: 'video2' } })
await waitJobs(servers)
})
it('Should list jobs', async function () {
- const res = await getJobsList(servers[1].url, servers[1].accessToken, 'completed')
- expect(res.body.total).to.be.above(2)
- expect(res.body.data).to.have.length.above(2)
+ const body = await servers[1].jobs.getJobsList({ state: 'completed' })
+ expect(body.total).to.be.above(2)
+ expect(body.data).to.have.length.above(2)
})
it('Should list jobs with sort, pagination and job type', async function () {
{
- const res = await getJobsListPaginationAndSort({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
+ const body = await servers[1].jobs.getJobsList({
state: 'completed',
start: 1,
count: 2,
sort: 'createdAt'
})
- expect(res.body.total).to.be.above(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.be.above(2)
+ expect(body.data).to.have.lengthOf(2)
- let job: Job = res.body.data[0]
+ let job = body.data[0]
// Skip repeat jobs
- if (job.type === 'videos-views') job = res.body.data[1]
+ if (job.type === 'videos-views') job = body.data[1]
expect(job.state).to.equal('completed')
expect(job.type.startsWith('activitypub-')).to.be.true
}
{
- const res = await getJobsListPaginationAndSort({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
+ const body = await servers[1].jobs.getJobsList({
state: 'completed',
start: 0,
count: 100,
sort: 'createdAt',
jobType: 'activitypub-http-broadcast'
})
- expect(res.body.total).to.be.above(2)
+ expect(body.total).to.be.above(2)
- for (const j of res.body.data as Job[]) {
+ for (const j of body.data) {
expect(j.type).to.equal('activitypub-http-broadcast')
}
}
})
it('Should list all jobs', async function () {
- const res = await getJobsList(servers[1].url, servers[1].accessToken)
-
- const jobs = res.body.data as Job[]
+ const body = await servers[1].jobs.getJobsList()
+ expect(body.total).to.be.above(2)
- expect(res.body.total).to.be.above(2)
+ const jobs = body.data
expect(jobs).to.have.length.above(2)
// We know there are a least 1 delayed job (video views) and 1 completed job (broadcast)
import * as chai from 'chai'
import {
cleanupTests,
- flushAndRunServer,
+ createSingleServer,
killallServers,
- makePingRequest,
- reRunServer,
- ServerInfo,
- setAccessTokensToServers
-} from '../../../../shared/extra-utils/index'
-import { getAuditLogs, getLogs } from '../../../../shared/extra-utils/logs/logs'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { uploadVideo } from '../../../../shared/extra-utils/videos/videos'
+ LogsCommand,
+ PeerTubeServer,
+ setAccessTokensToServers,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test logs', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
+ let logsCommand: LogsCommand
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
+
+ logsCommand = server.logs
})
describe('With the standard log file', function () {
it('Should get logs with a start date', async function () {
this.timeout(20000)
- await uploadVideo(server.url, server.accessToken, { name: 'video 1' })
+ await server.videos.upload({ attributes: { name: 'video 1' } })
await waitJobs([ server ])
const now = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 2' })
+ await server.videos.upload({ attributes: { name: 'video 2' } })
await waitJobs([ server ])
- const res = await getLogs(server.url, server.accessToken, now)
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 1')).to.be.false
expect(logsString.includes('video 2')).to.be.true
it('Should get logs with an end date', async function () {
this.timeout(30000)
- await uploadVideo(server.url, server.accessToken, { name: 'video 3' })
+ await server.videos.upload({ attributes: { name: 'video 3' } })
await waitJobs([ server ])
const now1 = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 4' })
+ await server.videos.upload({ attributes: { name: 'video 4' } })
await waitJobs([ server ])
const now2 = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 5' })
+ await server.videos.upload({ attributes: { name: 'video 5' } })
await waitJobs([ server ])
- const res = await getLogs(server.url, server.accessToken, now1, now2)
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now1, endDate: now2 })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 3')).to.be.false
expect(logsString.includes('video 4')).to.be.true
const now = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 6' })
+ await server.videos.upload({ attributes: { name: 'video 6' } })
await waitJobs([ server ])
{
- const res = await getLogs(server.url, server.accessToken, now, undefined, 'info')
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 6')).to.be.true
}
{
- const res = await getLogs(server.url, server.accessToken, now, undefined, 'warn')
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now, level: 'warn' })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 6')).to.be.false
}
const now = new Date()
- await makePingRequest(server)
+ await server.servers.ping()
- const res = await getLogs(server.url, server.accessToken, now, undefined, 'info')
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('/api/v1/ping')).to.be.true
})
it('Should not log ping requests', async function () {
this.timeout(30000)
- killallServers([ server ])
+ await killallServers([ server ])
- await reRunServer(server, { log: { log_ping_requests: false } })
+ await server.run({ log: { log_ping_requests: false } })
const now = new Date()
- await makePingRequest(server)
+ await server.servers.ping()
- const res = await getLogs(server.url, server.accessToken, now, undefined, 'info')
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('/api/v1/ping')).to.be.false
})
it('Should get logs with a start date', async function () {
this.timeout(20000)
- await uploadVideo(server.url, server.accessToken, { name: 'video 7' })
+ await server.videos.upload({ attributes: { name: 'video 7' } })
await waitJobs([ server ])
const now = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 8' })
+ await server.videos.upload({ attributes: { name: 'video 8' } })
await waitJobs([ server ])
- const res = await getAuditLogs(server.url, server.accessToken, now)
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getAuditLogs({ startDate: now })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 7')).to.be.false
expect(logsString.includes('video 8')).to.be.true
- expect(res.body).to.have.lengthOf(1)
+ expect(body).to.have.lengthOf(1)
- const item = res.body[0]
+ const item = body[0]
const message = JSON.parse(item.message)
expect(message.domain).to.equal('videos')
it('Should get logs with an end date', async function () {
this.timeout(30000)
- await uploadVideo(server.url, server.accessToken, { name: 'video 9' })
+ await server.videos.upload({ attributes: { name: 'video 9' } })
await waitJobs([ server ])
const now1 = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 10' })
+ await server.videos.upload({ attributes: { name: 'video 10' } })
await waitJobs([ server ])
const now2 = new Date()
- await uploadVideo(server.url, server.accessToken, { name: 'video 11' })
+ await server.videos.upload({ attributes: { name: 'video 11' } })
await waitJobs([ server ])
- const res = await getAuditLogs(server.url, server.accessToken, now1, now2)
- const logsString = JSON.stringify(res.body)
+ const body = await logsCommand.getAuditLogs({ startDate: now1, endDate: now2 })
+ const logsString = JSON.stringify(body)
expect(logsString.includes('video 9')).to.be.false
expect(logsString.includes('video 10')).to.be.true
import 'mocha'
import * as request from 'supertest'
-import { ServerInfo } from '../../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Start and stop server without web client routes', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1, {}, [ '--no-client' ])
+ server = await createSingleServer(1, {}, { peertubeArgs: [ '--no-client' ] })
})
it('Should fail getting the client', function () {
import 'mocha'
import * as chai from 'chai'
-import { HttpStatusCode } from '@shared/core-utils'
import {
cleanupTests,
- closeAllSequelize,
- flushAndRunServer,
- getConfig,
- getMyUserInformation,
- getPlugin,
- getPluginPackageJSON,
- getPluginTestPath,
- getPublicSettings,
- installPlugin,
+ createSingleServer,
killallServers,
- listAvailablePlugins,
- listPlugins,
- reRunServer,
- ServerInfo,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers,
- setPluginVersion,
testHelloWorldRegisteredSettings,
- uninstallPlugin,
- updateCustomSubConfig,
- updateMyUser,
- updatePlugin,
- updatePluginPackageJSON,
- updatePluginSettings,
- wait,
- waitUntilLog
+ wait
} from '@shared/extra-utils'
-import { PeerTubePlugin, PeerTubePluginIndex, PluginPackageJson, PluginType, PublicServerSetting, ServerConfig, User } from '@shared/models'
+import { HttpStatusCode, PluginType } from '@shared/models'
const expect = chai.expect
describe('Test plugins', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer = null
+ let command: PluginsCommand
before(async function () {
this.timeout(30000)
index: { check_latest_versions_interval: '5 seconds' }
}
}
- server = await flushAndRunServer(1, configOverride)
+ server = await createSingleServer(1, configOverride)
await setAccessTokensToServers([ server ])
+
+ command = server.plugins
})
it('Should list and search available plugins and themes', async function () {
this.timeout(30000)
{
- const res = await listAvailablePlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body = await command.listAvailable({
count: 1,
start: 0,
pluginType: PluginType.THEME,
search: 'background-red'
})
- expect(res.body.total).to.be.at.least(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.be.at.least(1)
+ expect(body.data).to.have.lengthOf(1)
}
{
- const res1 = await listAvailablePlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body1 = await command.listAvailable({
count: 2,
start: 0,
sort: 'npmName'
})
- const data1: PeerTubePluginIndex[] = res1.body.data
+ expect(body1.total).to.be.at.least(2)
- expect(res1.body.total).to.be.at.least(2)
+ const data1 = body1.data
expect(data1).to.have.lengthOf(2)
- const res2 = await listAvailablePlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body2 = await command.listAvailable({
count: 2,
start: 0,
sort: '-npmName'
})
- const data2: PeerTubePluginIndex[] = res2.body.data
+ expect(body2.total).to.be.at.least(2)
- expect(res2.body.total).to.be.at.least(2)
+ const data2 = body2.data
expect(data2).to.have.lengthOf(2)
expect(data1[0].npmName).to.not.equal(data2[0].npmName)
}
{
- const res = await listAvailablePlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body = await command.listAvailable({
count: 10,
start: 0,
pluginType: PluginType.THEME,
search: 'background-red',
currentPeerTubeEngine: '1.0.0'
})
- const data: PeerTubePluginIndex[] = res.body.data
- const p = data.find(p => p.npmName === 'peertube-theme-background-red')
+ const p = body.data.find(p => p.npmName === 'peertube-theme-background-red')
expect(p).to.be.undefined
}
})
it('Should install a plugin and a theme', async function () {
this.timeout(30000)
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-theme-background-red'
- })
+ await command.install({ npmName: 'peertube-plugin-hello-world' })
+ await command.install({ npmName: 'peertube-theme-background-red' })
})
it('Should have the plugin loaded in the configuration', async function () {
- const res = await getConfig(server.url)
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const theme = config.theme.registered.find(r => r.name === 'background-red')
expect(theme).to.not.be.undefined
})
it('Should update the default theme in the configuration', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, { theme: { default: 'background-red' } })
-
- const res = await getConfig(server.url)
- const config: ServerConfig = res.body
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ theme: { default: 'background-red' }
+ }
+ })
+ const config = await server.config.getConfig()
expect(config.theme.default).to.equal('background-red')
})
it('Should update my default theme', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: server.accessToken,
- theme: 'background-red'
- })
+ await server.users.updateMe({ theme: 'background-red' })
- const res = await getMyUserInformation(server.url, server.accessToken)
- expect((res.body as User).theme).to.equal('background-red')
+ const user = await server.users.getMyInfo()
+ expect(user.theme).to.equal('background-red')
})
it('Should list plugins and themes', async function () {
{
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body = await command.list({
count: 1,
start: 0,
pluginType: PluginType.THEME
})
- const data: PeerTubePlugin[] = res.body.data
+ expect(body.total).to.be.at.least(1)
- expect(res.body.total).to.be.at.least(1)
+ const data = body.data
expect(data).to.have.lengthOf(1)
expect(data[0].name).to.equal('background-red')
}
{
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const { data } = await command.list({
count: 2,
start: 0,
sort: 'name'
})
- const data: PeerTubePlugin[] = res.body.data
expect(data[0].name).to.equal('background-red')
expect(data[1].name).to.equal('hello-world')
}
{
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
+ const body = await command.list({
count: 2,
start: 1,
sort: 'name'
})
- const data: PeerTubePlugin[] = res.body.data
- expect(data[0].name).to.equal('hello-world')
+ expect(body.data[0].name).to.equal('hello-world')
}
})
})
it('Should get public settings', async function () {
- const res = await getPublicSettings({ url: server.url, npmName: 'peertube-plugin-hello-world' })
-
- const publicSettings = (res.body as PublicServerSetting).publicSettings
+ const body = await command.getPublicSettings({ npmName: 'peertube-plugin-hello-world' })
+ const publicSettings = body.publicSettings
expect(Object.keys(publicSettings)).to.have.lengthOf(1)
expect(Object.keys(publicSettings)).to.deep.equal([ 'user-name' ])
'admin-name': 'Cid'
}
- await updatePluginSettings({
- url: server.url,
- accessToken: server.accessToken,
+ await command.updateSettings({
npmName: 'peertube-plugin-hello-world',
settings
})
it('Should have watched settings changes', async function () {
this.timeout(10000)
- await waitUntilLog(server, 'Settings changed!')
+ await server.servers.waitUntilLog('Settings changed!')
})
it('Should get a plugin and a theme', async function () {
{
- const res = await getPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- const plugin: PeerTubePlugin = res.body
+ const plugin = await command.get({ npmName: 'peertube-plugin-hello-world' })
expect(plugin.type).to.equal(PluginType.PLUGIN)
expect(plugin.name).to.equal('hello-world')
}
{
- const res = await getPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-theme-background-red'
- })
-
- const plugin: PeerTubePlugin = res.body
+ const plugin = await command.get({ npmName: 'peertube-theme-background-red' })
expect(plugin.type).to.equal(PluginType.THEME)
expect(plugin.name).to.equal('background-red')
await wait(6000)
// Fake update our plugin version
- await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
+ await server.sql.setPluginVersion('hello-world', '0.0.1')
// Fake update package.json
- const packageJSON: PluginPackageJson = await getPluginPackageJSON(server, 'peertube-plugin-hello-world')
+ const packageJSON = await command.getPackageJSON('peertube-plugin-hello-world')
const oldVersion = packageJSON.version
packageJSON.version = '0.0.1'
- await updatePluginPackageJSON(server, 'peertube-plugin-hello-world', packageJSON)
+ await command.updatePackageJSON('peertube-plugin-hello-world', packageJSON)
// Restart the server to take into account this change
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
{
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
- pluginType: PluginType.PLUGIN
- })
-
- const plugin: PeerTubePlugin = res.body.data[0]
+ const body = await command.list({ pluginType: PluginType.PLUGIN })
+ const plugin = body.data[0]
expect(plugin.version).to.equal('0.0.1')
expect(plugin.latestVersion).to.exist
expect(plugin.latestVersion).to.not.equal('0.0.1')
}
{
- await updatePlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
- pluginType: PluginType.PLUGIN
- })
+ await command.update({ npmName: 'peertube-plugin-hello-world' })
- const plugin: PeerTubePlugin = res.body.data[0]
+ const body = await command.list({ pluginType: PluginType.PLUGIN })
+ const plugin = body.data[0]
expect(plugin.version).to.equal(oldVersion)
- const updatedPackageJSON: PluginPackageJson = await getPluginPackageJSON(server, 'peertube-plugin-hello-world')
+ const updatedPackageJSON = await command.getPackageJSON('peertube-plugin-hello-world')
expect(updatedPackageJSON.version).to.equal(oldVersion)
}
})
it('Should uninstall the plugin', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
- pluginType: PluginType.PLUGIN
- })
+ await command.uninstall({ npmName: 'peertube-plugin-hello-world' })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.list({ pluginType: PluginType.PLUGIN })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should list uninstalled plugins', async function () {
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
- pluginType: PluginType.PLUGIN,
- uninstalled: true
- })
-
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await command.list({ pluginType: PluginType.PLUGIN, uninstalled: true })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const plugin: PeerTubePlugin = res.body.data[0]
+ const plugin = body.data[0]
expect(plugin.name).to.equal('hello-world')
expect(plugin.enabled).to.be.false
expect(plugin.uninstalled).to.be.true
})
it('Should uninstall the theme', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-theme-background-red'
- })
+ await command.uninstall({ npmName: 'peertube-theme-background-red' })
})
it('Should have updated the configuration', async function () {
- // get /config (default theme + registered themes + registered plugins)
- const res = await getConfig(server.url)
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
expect(config.theme.default).to.equal('default')
})
it('Should have updated the user theme', async function () {
- const res = await getMyUserInformation(server.url, server.accessToken)
- expect((res.body as User).theme).to.equal('instance-default')
+ const user = await server.users.getMyInfo()
+ expect(user.theme).to.equal('instance-default')
})
it('Should not install a broken plugin', async function () {
this.timeout(60000)
async function check () {
- const res = await listPlugins({
- url: server.url,
- accessToken: server.accessToken,
- pluginType: PluginType.PLUGIN
- })
-
- const plugins: PeerTubePlugin[] = res.body.data
-
+ const body = await command.list({ pluginType: PluginType.PLUGIN })
+ const plugins = body.data
expect(plugins.find(p => p.name === 'test-broken')).to.not.exist
}
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-broken'),
+ await command.install({
+ path: PluginsCommand.getPluginTestPath('-broken'),
expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await check()
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
await check()
})
after(async function () {
- await closeAllSequelize([ server ])
await cleanupTests([ server ])
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import 'mocha'
-import * as chai from 'chai'
-import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils'
-import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-
-const expect = chai.expect
+import { expect } from 'chai'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test application behind a reverse proxy', function () {
- let server = null
- let videoId
+ let server: PeerTubeServer
+ let videoId: string
before(async function () {
this.timeout(30000)
}
}
- server = await flushAndRunServer(1, config)
+ server = await createSingleServer(1, config)
await setAccessTokensToServers([ server ])
- const { body } = await uploadVideo(server.url, server.accessToken, {})
- videoId = body.video.uuid
+ const { uuid } = await server.videos.upload()
+ videoId = uuid
})
it('Should view a video only once with the same IP by default', async function () {
this.timeout(20000)
- await viewVideo(server.url, videoId)
- await viewVideo(server.url, videoId)
+ await server.videos.view({ id: videoId })
+ await server.videos.view({ id: videoId })
// Wait the repeatable job
await wait(8000)
- const { body } = await getVideo(server.url, videoId)
- expect(body.views).to.equal(1)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.views).to.equal(1)
})
it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
this.timeout(20000)
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.1,127.0.0.1')
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.2,127.0.0.1')
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.1,127.0.0.1' })
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.2,127.0.0.1' })
// Wait the repeatable job
await wait(8000)
- const { body } = await getVideo(server.url, videoId)
- expect(body.views).to.equal(3)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.views).to.equal(3)
})
it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
this.timeout(20000)
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.5,0.0.0.3,127.0.0.1')
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.4,0.0.0.3,::ffff:127.0.0.1' })
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.5,0.0.0.3,127.0.0.1' })
// Wait the repeatable job
await wait(8000)
- const { body } = await getVideo(server.url, videoId)
- expect(body.views).to.equal(4)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.views).to.equal(4)
})
it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
this.timeout(20000)
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.6,127.0.0.1')
- await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.7,127.0.0.1')
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.8,0.0.0.6,127.0.0.1' })
+ await server.videos.view({ id: videoId, xForwardedFor: '0.0.0.8,0.0.0.7,127.0.0.1' })
// Wait the repeatable job
await wait(8000)
- const { body } = await getVideo(server.url, videoId)
- expect(body.views).to.equal(6)
+ const video = await server.videos.get({ id: videoId })
+ expect(video.views).to.equal(6)
})
it('Should rate limit logins', async function () {
const user = { username: 'root', password: 'fail' }
for (let i = 0; i < 19; i++) {
- await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
- await userLogin(server, user, HttpStatusCode.TOO_MANY_REQUESTS_429)
+ await server.login.login({ user, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
})
it('Should rate limit signup', async function () {
for (let i = 0; i < 10; i++) {
try {
- await registerUser(server.url, 'test' + i, 'password')
+ await server.users.register({ username: 'test' + i })
} catch {
// empty
}
}
- await registerUser(server.url, 'test42', 'password', HttpStatusCode.TOO_MANY_REQUESTS_429)
+ await server.users.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
})
it('Should not rate limit failed signup', async function () {
await wait(7000)
for (let i = 0; i < 3; i++) {
- await registerUser(server.url, 'test' + i, 'password', HttpStatusCode.CONFLICT_409)
+ await server.users.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 })
}
- await registerUser(server.url, 'test43', 'password', HttpStatusCode.NO_CONTENT_204)
+ await server.users.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
})
for (let i = 0; i < 100; i++) {
try {
- await getVideo(server.url, videoId)
+ await server.videos.get({ id: videoId })
} catch {
// don't care if it fails
}
}
- await getVideo(server.url, videoId, HttpStatusCode.TOO_MANY_REQUESTS_429)
+ await server.videos.get({ id: videoId, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/extra-utils'
import { Video, VideoPlaylistPrivacy } from '@shared/models'
-import {
- addVideoInPlaylist,
- createVideoPlaylist,
- getOEmbed,
- getVideosList,
- ServerInfo,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- uploadVideo
-} from '../../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
const expect = chai.expect
describe('Test services', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer = null
let playlistUUID: string
let playlistDisplayName: string
let video: Video
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
{
- const videoAttributes = {
- name: 'my super name'
- }
- await uploadVideo(server.url, server.accessToken, videoAttributes)
+ const attributes = { name: 'my super name' }
+ await server.videos.upload({ attributes })
- const res = await getVideosList(server.url)
- video = res.body.data[0]
+ const { data } = await server.videos.list()
+ video = data[0]
}
{
- const res = await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ const created = await server.playlists.create({
+ attributes: {
displayName: 'The Life and Times of Scrooge McDuck',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: server.store.channel.id
}
})
- playlistUUID = res.body.videoPlaylist.uuid
+ playlistUUID = created.uuid
playlistDisplayName = 'The Life and Times of Scrooge McDuck'
- await addVideoInPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: res.body.videoPlaylist.id,
- elementAttrs: {
+ await server.playlists.addElement({
+ playlistId: created.id,
+ attributes: {
videoId: video.id
}
})
for (const basePath of [ '/videos/watch/', '/w/' ]) {
const oembedUrl = 'http://localhost:' + server.port + basePath + video.uuid
- const res = await getOEmbed(server.url, oembedUrl)
+ const res = await server.services.getOEmbed({ oembedUrl })
const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' +
`title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` +
'frameborder="0" allowfullscreen></iframe>'
expect(res.body.html).to.equal(expectedHtml)
expect(res.body.title).to.equal(video.name)
- expect(res.body.author_name).to.equal(server.videoChannel.displayName)
+ expect(res.body.author_name).to.equal(server.store.channel.displayName)
expect(res.body.width).to.equal(560)
expect(res.body.height).to.equal(315)
expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl)
for (const basePath of [ '/videos/watch/playlist/', '/w/p/' ]) {
const oembedUrl = 'http://localhost:' + server.port + basePath + playlistUUID
- const res = await getOEmbed(server.url, oembedUrl)
+ const res = await server.services.getOEmbed({ oembedUrl })
const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' +
`title="${playlistDisplayName}" src="http://localhost:${server.port}/video-playlists/embed/${playlistUUID}" ` +
'frameborder="0" allowfullscreen></iframe>'
expect(res.body.html).to.equal(expectedHtml)
expect(res.body.title).to.equal('The Life and Times of Scrooge McDuck')
- expect(res.body.author_name).to.equal(server.videoChannel.displayName)
+ expect(res.body.author_name).to.equal(server.store.channel.displayName)
expect(res.body.width).to.equal(560)
expect(res.body.height).to.equal(315)
expect(res.body.thumbnail_url).exist
const maxHeight = 50
const maxWidth = 50
- const res = await getOEmbed(server.url, oembedUrl, format, maxHeight, maxWidth)
+ const res = await server.services.getOEmbed({ oembedUrl, format, maxHeight, maxWidth })
const expectedHtml = '<iframe width="50" height="50" sandbox="allow-same-origin allow-scripts" ' +
`title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` +
'frameborder="0" allowfullscreen></iframe>'
expect(res.body.html).to.equal(expectedHtml)
expect(res.body.title).to.equal(video.name)
- expect(res.body.author_name).to.equal(server.videoChannel.displayName)
+ expect(res.body.author_name).to.equal(server.store.channel.displayName)
expect(res.body.height).to.equal(50)
expect(res.body.width).to.equal(50)
expect(res.body).to.not.have.property('thumbnail_url')
import 'mocha'
import * as chai from 'chai'
import {
- addVideoChannel,
cleanupTests,
- createUser,
- createVideoPlaylist,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- follow,
- ServerInfo,
- unfollow,
- updateCustomSubConfig,
- uploadVideo,
- userLogin,
- viewVideo,
- wait
-} from '../../../../shared/extra-utils'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { getStats } from '../../../../shared/extra-utils/server/stats'
-import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments'
-import { ServerStats } from '../../../../shared/models/server/server-stats.model'
-import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
-import { ActivityType } from '@shared/models'
+ PeerTubeServer,
+ setAccessTokensToServers,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { ActivityType, VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test stats (excluding redundancy)', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let channelId
const user = {
username: 'user1',
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
- const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { fixture: 'video_short.webm' })
- const videoUUID = resVideo.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { fixture: 'video_short.webm' } })
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment')
+ await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
- await viewVideo(servers[0].url, videoUUID)
+ await servers[0].videos.view({ id: uuid })
// Wait the video views repeatable job
await wait(8000)
- await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
+ await servers[2].follows.follow({ hosts: [ servers[0].url ] })
await waitJobs(servers)
})
it('Should have the correct stats on instance 1', async function () {
- const res = await getStats(servers[0].url)
- const data: ServerStats = res.body
+ const data = await servers[0].stats.get()
expect(data.totalLocalVideoComments).to.equal(1)
expect(data.totalLocalVideos).to.equal(1)
})
it('Should have the correct stats on instance 2', async function () {
- const res = await getStats(servers[1].url)
- const data: ServerStats = res.body
+ const data = await servers[1].stats.get()
expect(data.totalLocalVideoComments).to.equal(0)
expect(data.totalLocalVideos).to.equal(0)
})
it('Should have the correct stats on instance 3', async function () {
- const res = await getStats(servers[2].url)
- const data: ServerStats = res.body
+ const data = await servers[2].stats.get()
expect(data.totalLocalVideoComments).to.equal(0)
expect(data.totalLocalVideos).to.equal(0)
it('Should have the correct total videos stats after an unfollow', async function () {
this.timeout(15000)
- await unfollow(servers[2].url, servers[2].accessToken, servers[0])
+ await servers[2].follows.unfollow({ target: servers[0] })
await waitJobs(servers)
- const res = await getStats(servers[2].url)
- const data: ServerStats = res.body
+ const data = await servers[2].stats.get()
expect(data.totalVideos).to.equal(0)
})
const server = servers[0]
{
- const res = await getStats(server.url)
- const data: ServerStats = res.body
+ const data = await server.stats.get()
+
expect(data.totalDailyActiveUsers).to.equal(1)
expect(data.totalWeeklyActiveUsers).to.equal(1)
expect(data.totalMonthlyActiveUsers).to.equal(1)
}
{
- await userLogin(server, user)
+ await server.login.getAccessToken(user)
+
+ const data = await server.stats.get()
- const res = await getStats(server.url)
- const data: ServerStats = res.body
expect(data.totalDailyActiveUsers).to.equal(2)
expect(data.totalWeeklyActiveUsers).to.equal(2)
expect(data.totalMonthlyActiveUsers).to.equal(2)
const server = servers[0]
{
- const res = await getStats(server.url)
- const data: ServerStats = res.body
+ const data = await server.stats.get()
+
expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
}
{
- const channelAttributes = {
+ const attributes = {
name: 'stats_channel',
displayName: 'My stats channel'
}
- const resChannel = await addVideoChannel(server.url, server.accessToken, channelAttributes)
- channelId = resChannel.body.videoChannel.id
+ const created = await server.channels.create({ attributes })
+ channelId = created.id
+
+ const data = await server.stats.get()
- const res = await getStats(server.url)
- const data: ServerStats = res.body
expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
}
{
- await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.webm', channelId })
+ await server.videos.upload({ attributes: { fixture: 'video_short.webm', channelId } })
+
+ const data = await server.stats.get()
- const res = await getStats(server.url)
- const data: ServerStats = res.body
expect(data.totalLocalDailyActiveVideoChannels).to.equal(2)
expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(2)
expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(2)
const server = servers[0]
{
- const resStats = await getStats(server.url)
- const dataStats: ServerStats = resStats.body
- expect(dataStats.totalLocalPlaylists).to.equal(0)
+ const data = await server.stats.get()
+ expect(data.totalLocalPlaylists).to.equal(0)
}
{
- await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ await server.playlists.create({
+ attributes: {
displayName: 'playlist for count',
privacy: VideoPlaylistPrivacy.PUBLIC,
videoChannelId: channelId
}
})
- const resStats = await getStats(server.url)
- const dataStats: ServerStats = resStats.body
- expect(dataStats.totalLocalPlaylists).to.equal(1)
+ const data = await server.stats.get()
+ expect(data.totalLocalPlaylists).to.equal(1)
}
})
it('Should correctly count video file sizes if transcoding is enabled', async function () {
this.timeout(60000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- enabled: true,
- webtorrent: {
- enabled: true
- },
- hls: {
- enabled: true
- },
- resolutions: {
- '0p': false,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: true,
+ webtorrent: {
+ enabled: true
+ },
+ hls: {
+ enabled: true
+ },
+ resolutions: {
+ '0p': false,
+ '240p': false,
+ '360p': false,
+ '480p': false,
+ '720p': false,
+ '1080p': false,
+ '1440p': false,
+ '2160p': false
+ }
}
}
})
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video', fixture: 'video_short.webm' })
+ await servers[0].videos.upload({ attributes: { name: 'video', fixture: 'video_short.webm' } })
await waitJobs(servers)
{
- const res = await getStats(servers[1].url)
- const data: ServerStats = res.body
+ const data = await servers[1].stats.get()
expect(data.totalLocalVideoFilesSize).to.equal(0)
}
{
- const res = await getStats(servers[0].url)
- const data: ServerStats = res.body
+ const data = await servers[0].stats.get()
expect(data.totalLocalVideoFilesSize).to.be.greaterThan(500000)
expect(data.totalLocalVideoFilesSize).to.be.lessThan(600000)
}
it('Should have the correct AP stats', async function () {
this.timeout(60000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: false
+ }
}
})
- const res1 = await getStats(servers[1].url)
- const first = res1.body as ServerStats
+ const first = await servers[1].stats.get()
for (let i = 0; i < 10; i++) {
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
+ await servers[0].videos.upload({ attributes: { name: 'video' } })
}
await waitJobs(servers)
await wait(6000)
- const res2 = await getStats(servers[1].url)
- const second: ServerStats = res2.body
-
+ const second = await servers[1].stats.get()
expect(second.totalActivityPubMessagesProcessed).to.be.greaterThan(first.totalActivityPubMessagesProcessed)
+
const apTypes: ActivityType[] = [
'Create', 'Update', 'Delete', 'Follow', 'Accept', 'Announce', 'Undo', 'Like', 'Reject', 'View', 'Dislike', 'Flag'
]
await wait(6000)
- const res3 = await getStats(servers[1].url)
- const third: ServerStats = res3.body
-
+ const third = await servers[1].stats.get()
expect(third.totalActivityPubMessagesWaiting).to.equal(0)
expect(third.activityPubMessagesProcessedPerSecond).to.be.lessThan(second.activityPubMessagesProcessedPerSecond)
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await,@typescript-eslint/no-floating-promises */
-import * as magnetUtil from 'magnet-uri'
import 'mocha'
-import {
- cleanupTests,
- flushAndRunServer,
- getVideo,
- killallServers,
- reRunServer,
- ServerInfo,
- uploadVideo
-} from '../../../../shared/extra-utils'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { VideoDetails } from '../../../../shared/models/videos'
+import * as magnetUtil from 'magnet-uri'
import * as WebTorrent from 'webtorrent'
+import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
describe('Test tracker', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let badMagnet: string
let goodMagnet: string
before(async function () {
this.timeout(60000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
{
- const res = await uploadVideo(server.url, server.accessToken, {})
- const videoUUID = res.body.video.uuid
-
- const resGet = await getVideo(server.url, videoUUID)
- const video: VideoDetails = resGet.body
+ const { uuid } = await server.videos.upload()
+ const video = await server.videos.get({ id: uuid })
goodMagnet = video.files[0].magnetUri
const parsed = magnetUtil.decode(goodMagnet)
const errCb = () => done(new Error('Tracker is enabled'))
killallServers([ server ])
-
- reRunServer(server, { tracker: { enabled: false } })
+ .then(() => server.run({ tracker: { enabled: false } }))
.then(() => {
const webtorrent = new WebTorrent()
this.timeout(20000)
killallServers([ server ])
-
- reRunServer(server)
+ .then(() => server.run())
.then(() => {
const webtorrent = new WebTorrent()
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- follow,
- getVideosList,
- unfollow,
- updateVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
-import { Video, VideoChannel } from '../../../../shared/models/videos'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- addUserSubscription,
- areSubscriptionsExist,
- getUserSubscription,
- listUserSubscriptions,
- listUserSubscriptionVideos,
- removeUserSubscription
-} from '../../../../shared/extra-utils/users/user-subscriptions'
+ PeerTubeServer,
+ setAccessTokensToServers,
+ SubscriptionsCommand,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test users subscriptions', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
const users: { accessToken: string }[] = []
let video3UUID: string
+ let command: SubscriptionsCommand
+
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
{
for (const server of servers) {
const user = { username: 'user' + server.serverNumber, password: 'password' }
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
+ await server.users.create({ username: user.username, password: user.password })
- const accessToken = await userLogin(server, user)
+ const accessToken = await server.login.getAccessToken(user)
users.push({ accessToken })
const videoName1 = 'video 1-' + server.serverNumber
- await uploadVideo(server.url, accessToken, { name: videoName1 })
+ await server.videos.upload({ token: accessToken, attributes: { name: videoName1 } })
const videoName2 = 'video 2-' + server.serverNumber
- await uploadVideo(server.url, accessToken, { name: videoName2 })
+ await server.videos.upload({ token: accessToken, attributes: { name: videoName2 } })
}
}
await waitJobs(servers)
+
+ command = servers[0].subscriptions
})
it('Should display videos of server 2 on server 1', async function () {
- const res = await getVideosList(servers[0].url)
+ const { total } = await servers[0].videos.list()
- expect(res.body.total).to.equal(4)
+ expect(total).to.equal(4)
})
it('User of server 1 should follow user of server 3 and root of server 1', async function () {
this.timeout(60000)
- await addUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:' + servers[2].port)
- await addUserSubscription(servers[0].url, users[0].accessToken, 'root_channel@localhost:' + servers[0].port)
+ await command.add({ token: users[0].accessToken, targetUri: 'user3_channel@localhost:' + servers[2].port })
+ await command.add({ token: users[0].accessToken, targetUri: 'root_channel@localhost:' + servers[0].port })
await waitJobs(servers)
- const res = await uploadVideo(servers[2].url, users[2].accessToken, { name: 'video server 3 added after follow' })
- video3UUID = res.body.video.uuid
+ const attributes = { name: 'video server 3 added after follow' }
+ const { uuid } = await servers[2].videos.upload({ token: users[2].accessToken, attributes })
+ video3UUID = uuid
await waitJobs(servers)
})
it('Should not display videos of server 3 on server 1', async function () {
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(4)
- expect(res.body.total).to.equal(4)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.name).to.not.contain('1-3')
expect(video.name).to.not.contain('2-3')
expect(video.name).to.not.contain('video server 3 added after follow')
it('Should list subscriptions', async function () {
{
- const res = await listUserSubscriptions({ url: servers[0].url, token: servers[0].accessToken })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.list()
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
- const res = await listUserSubscriptions({ url: servers[0].url, token: users[0].accessToken, sort: 'createdAt' })
- expect(res.body.total).to.equal(2)
+ const body = await command.list({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const subscriptions: VideoChannel[] = res.body.data
+ const subscriptions = body.data
expect(subscriptions).to.be.an('array')
expect(subscriptions).to.have.lengthOf(2)
it('Should get subscription', async function () {
{
- const res = await getUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:' + servers[2].port)
- const videoChannel: VideoChannel = res.body
+ const videoChannel = await command.get({ token: users[0].accessToken, uri: 'user3_channel@localhost:' + servers[2].port })
expect(videoChannel.name).to.equal('user3_channel')
expect(videoChannel.host).to.equal('localhost:' + servers[2].port)
}
{
- const res = await getUserSubscription(servers[0].url, users[0].accessToken, 'root_channel@localhost:' + servers[0].port)
- const videoChannel: VideoChannel = res.body
+ const videoChannel = await command.get({ token: users[0].accessToken, uri: 'root_channel@localhost:' + servers[0].port })
expect(videoChannel.name).to.equal('root_channel')
expect(videoChannel.host).to.equal('localhost:' + servers[0].port)
'user3_channel@localhost:' + servers[0].port
]
- const res = await areSubscriptionsExist(servers[0].url, users[0].accessToken, uris)
- const body = res.body
+ const body = await command.exist({ token: users[0].accessToken, uris })
expect(body['user3_channel@localhost:' + servers[2].port]).to.be.true
expect(body['root2_channel@localhost:' + servers[0].port]).to.be.false
it('Should search among subscriptions', async function () {
{
- const res = await listUserSubscriptions({
- url: servers[0].url,
- token: users[0].accessToken,
- sort: '-createdAt',
- search: 'user3_channel'
- })
- expect(res.body.total).to.equal(1)
-
- const subscriptions = res.body.data
- expect(subscriptions).to.have.lengthOf(1)
+ const body = await command.list({ token: users[0].accessToken, sort: '-createdAt', search: 'user3_channel' })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
}
{
- const res = await listUserSubscriptions({
- url: servers[0].url,
- token: users[0].accessToken,
- sort: '-createdAt',
- search: 'toto'
- })
- expect(res.body.total).to.equal(0)
-
- const subscriptions = res.body.data
- expect(subscriptions).to.have.lengthOf(0)
+ const body = await command.list({ token: users[0].accessToken, sort: '-createdAt', search: 'toto' })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
})
it('Should list subscription videos', async function () {
{
- const res = await listUserSubscriptionVideos(servers[0].url, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.listVideos()
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(3)
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(3)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos).to.have.lengthOf(3)
this.timeout(60000)
const videoName = 'video server 1 added after follow'
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: videoName })
+ await servers[0].videos.upload({ attributes: { name: videoName } })
await waitJobs(servers)
{
- const res = await listUserSubscriptionVideos(servers[0].url, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.listVideos()
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(4)
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(4)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos).to.have.lengthOf(4)
}
{
- const res = await getVideosList(servers[0].url)
+ const { data, total } = await servers[0].videos.list()
+ expect(total).to.equal(5)
- expect(res.body.total).to.equal(5)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.name).to.not.contain('1-3')
expect(video.name).to.not.contain('2-3')
expect(video.name).to.not.contain('video server 3 added after follow')
it('Should have server 1 follow server 3 and display server 3 videos', async function () {
this.timeout(60000)
- await follow(servers[0].url, [ servers[2].url ], servers[0].accessToken)
+ await servers[0].follows.follow({ hosts: [ servers[2].url ] })
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
-
- expect(res.body.total).to.equal(8)
+ const { data, total } = await servers[0].videos.list()
+ expect(total).to.equal(8)
const names = [ '1-3', '2-3', 'video server 3 added after follow' ]
for (const name of names) {
- const video = res.body.data.find(v => v.name.indexOf(name) === -1)
+ const video = data.find(v => v.name.includes(name))
expect(video).to.not.be.undefined
}
})
it('Should remove follow server 1 -> server 3 and hide server 3 videos', async function () {
this.timeout(60000)
- await unfollow(servers[0].url, servers[0].accessToken, servers[2])
+ await servers[0].follows.unfollow({ target: servers[2] })
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(5)
- expect(res.body.total).to.equal(5)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.name).to.not.contain('1-3')
expect(video.name).to.not.contain('2-3')
expect(video.name).to.not.contain('video server 3 added after follow')
it('Should still list subscription videos', async function () {
{
- const res = await listUserSubscriptionVideos(servers[0].url, servers[0].accessToken)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await command.listVideos()
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
}
{
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(4)
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(4)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos).to.have.lengthOf(4)
it('Should update a video of server 3 and see the updated video on server 1', async function () {
this.timeout(30000)
- await updateVideo(servers[2].url, users[2].accessToken, video3UUID, { name: 'video server 3 added after follow updated' })
+ await servers[2].videos.update({ id: video3UUID, attributes: { name: 'video server 3 added after follow updated' } })
await waitJobs(servers)
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- const videos: Video[] = res.body.data
- expect(videos[2].name).to.equal('video server 3 added after follow updated')
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.data[2].name).to.equal('video server 3 added after follow updated')
})
it('Should remove user of server 3 subscription', async function () {
this.timeout(30000)
- await removeUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:' + servers[2].port)
+ await command.remove({ token: users[0].accessToken, uri: 'user3_channel@localhost:' + servers[2].port })
await waitJobs(servers)
})
it('Should not display its videos anymore', async function () {
- {
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(1)
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(1)
- const videos: Video[] = res.body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(1)
+ const videos = body.data
+ expect(videos).to.be.an('array')
+ expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('video server 1 added after follow')
- }
+ expect(videos[0].name).to.equal('video server 1 added after follow')
})
it('Should remove the root subscription and not display the videos anymore', async function () {
this.timeout(30000)
- await removeUserSubscription(servers[0].url, users[0].accessToken, 'root_channel@localhost:' + servers[0].port)
+ await command.remove({ token: users[0].accessToken, uri: 'root_channel@localhost:' + servers[0].port })
await waitJobs(servers)
{
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(0)
+ const body = await command.list({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(0)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos).to.have.lengthOf(0)
}
})
it('Should correctly display public videos on server 1', async function () {
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(5)
- expect(res.body.total).to.equal(5)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.name).to.not.contain('1-3')
expect(video.name).to.not.contain('2-3')
expect(video.name).to.not.contain('video server 3 added after follow updated')
it('Should follow user of server 3 again', async function () {
this.timeout(60000)
- await addUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:' + servers[2].port)
+ await command.add({ token: users[0].accessToken, targetUri: 'user3_channel@localhost:' + servers[2].port })
await waitJobs(servers)
{
- const res = await listUserSubscriptionVideos(servers[0].url, users[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(3)
+ const body = await command.listVideos({ token: users[0].accessToken, sort: 'createdAt' })
+ expect(body.total).to.equal(3)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos).to.be.an('array')
expect(videos).to.have.lengthOf(3)
}
{
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
+ expect(total).to.equal(5)
- expect(res.body.total).to.equal(5)
- for (const video of res.body.data) {
+ for (const video of data) {
expect(video.name).to.not.contain('1-3')
expect(video.name).to.not.contain('2-3')
expect(video.name).to.not.contain('video server 3 added after follow updated')
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { Account } from '../../../../shared/models/actors'
+import * as chai from 'chai'
import {
+ checkActorFilesWereRemoved,
checkTmpIsEmpty,
checkVideoFilesWereRemoved,
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getAccountVideos,
- getVideoChannelsList,
- removeUser,
- updateMyUser,
- userLogin
-} from '../../../../shared/extra-utils'
-import { getMyUserInformation, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../../../shared/extra-utils/index'
-import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../../../shared/extra-utils/users/accounts'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
-import { User } from '../../../../shared/models/users'
-import { VideoChannel } from '../../../../shared/models/videos'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+ PeerTubeServer,
+ saveVideoInServers,
+ setAccessTokensToServers,
+ testImage,
+ waitJobs
+} from '@shared/extra-utils'
+import { MyUser } from '@shared/models'
const expect = chai.expect
describe('Test users with multiple servers', function () {
- let servers: ServerInfo[] = []
- let user: User
+ let servers: PeerTubeServer[] = []
+
+ let user: MyUser
let userId: number
+
let videoUUID: string
let userAccessToken: string
let userAvatarFilename: string
before(async function () {
this.timeout(120_000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
await doubleFollow(servers[1], servers[2])
// The root user of server 1 is propagated to servers 2 and 3
- await uploadVideo(servers[0].url, servers[0].accessToken, {})
+ await servers[0].videos.upload()
{
- const user = {
- username: 'user1',
- password: 'password'
- }
- const res = await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: user.username,
- password: user.password
- })
- userId = res.body.user.id
- userAccessToken = await userLogin(servers[0], user)
+ const username = 'user1'
+ const created = await servers[0].users.create({ username })
+ userId = created.id
+ userAccessToken = await servers[0].login.getAccessToken(username)
}
{
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, {})
- videoUUID = resVideo.body.video.uuid
- }
+ const { uuid } = await servers[0].videos.upload({ token: userAccessToken })
+ videoUUID = uuid
- await waitJobs(servers)
+ await waitJobs(servers)
+
+ await saveVideoInServers(servers, videoUUID)
+ }
})
it('Should be able to update my display name', async function () {
this.timeout(10000)
- await updateMyUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- displayName: 'my super display name'
- })
-
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- user = res.body
+ await servers[0].users.updateMe({ displayName: 'my super display name' })
+ user = await servers[0].users.getMyInfo()
expect(user.account.displayName).to.equal('my super display name')
await waitJobs(servers)
it('Should be able to update my description', async function () {
this.timeout(10_000)
- await updateMyUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- description: 'my super description updated'
- })
+ await servers[0].users.updateMe({ description: 'my super description updated' })
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- user = res.body
+ user = await servers[0].users.getMyInfo()
expect(user.account.displayName).to.equal('my super display name')
expect(user.account.description).to.equal('my super description updated')
const fixture = 'avatar2.png'
- await updateMyAvatar({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- fixture
- })
-
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- user = res.body
+ await servers[0].users.updateMyAvatar({ fixture })
+ user = await servers[0].users.getMyInfo()
userAvatarFilename = user.account.avatar.path
await testImage(servers[0].url, 'avatar2-resized', userAvatarFilename, '.png')
let createdAt: string | Date
for (const server of servers) {
- const resAccounts = await getAccountsList(server.url, '-createdAt')
+ const body = await server.accounts.list({ sort: '-createdAt' })
- const resList = resAccounts.body.data.find(a => a.name === 'root' && a.host === 'localhost:' + servers[0].port) as Account
+ const resList = body.data.find(a => a.name === 'root' && a.host === 'localhost:' + servers[0].port)
expect(resList).not.to.be.undefined
- const resAccount = await getAccount(server.url, resList.name + '@' + resList.host)
- const account = resAccount.body as Account
+ const account = await server.accounts.get({ accountName: resList.name + '@' + resList.host })
if (!createdAt) createdAt = account.createdAt
it('Should list account videos', async function () {
for (const server of servers) {
- const res = await getAccountVideos(server.url, server.accessToken, 'user1@localhost:' + servers[0].port, 0, 5)
+ const { total, data } = await server.videos.listByAccount({ handle: 'user1@localhost:' + servers[0].port })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].uuid).to.equal(videoUUID)
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].uuid).to.equal(videoUUID)
}
})
it('Should search through account videos', async function () {
this.timeout(10_000)
- const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'Kami no chikara' })
+ const created = await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'Kami no chikara' } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getAccountVideos(server.url, server.accessToken, 'user1@localhost:' + servers[0].port, 0, 5, undefined, {
- search: 'Kami'
- })
-
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].uuid).to.equal(resVideo.body.video.uuid)
+ const { total, data } = await server.videos.listByAccount({ handle: 'user1@localhost:' + servers[0].port, search: 'Kami' })
+
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].uuid).to.equal(created.uuid)
}
})
this.timeout(10_000)
for (const server of servers) {
- const resAccounts = await getAccountsList(server.url, '-createdAt')
+ const body = await server.accounts.list({ sort: '-createdAt' })
- const accountDeleted = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:' + servers[0].port) as Account
+ const accountDeleted = body.data.find(a => a.name === 'user1' && a.host === 'localhost:' + servers[0].port)
expect(accountDeleted).not.to.be.undefined
- const resVideoChannels = await getVideoChannelsList(server.url, 0, 10)
- const videoChannelDeleted = resVideoChannels.body.data.find(a => {
- return a.displayName === 'Main user1 channel' && a.host === 'localhost:' + servers[0].port
- }) as VideoChannel
+ const { data } = await server.channels.list()
+ const videoChannelDeleted = data.find(a => a.displayName === 'Main user1 channel' && a.host === 'localhost:' + servers[0].port)
expect(videoChannelDeleted).not.to.be.undefined
}
- await removeUser(servers[0].url, userId, servers[0].accessToken)
+ await servers[0].users.remove({ userId })
await waitJobs(servers)
for (const server of servers) {
- const resAccounts = await getAccountsList(server.url, '-createdAt')
+ const body = await server.accounts.list({ sort: '-createdAt' })
- const accountDeleted = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:' + servers[0].port) as Account
+ const accountDeleted = body.data.find(a => a.name === 'user1' && a.host === 'localhost:' + servers[0].port)
expect(accountDeleted).to.be.undefined
- const resVideoChannels = await getVideoChannelsList(server.url, 0, 10)
- const videoChannelDeleted = resVideoChannels.body.data.find(a => {
- return a.name === 'Main user1 channel' && a.host === 'localhost:' + servers[0].port
- }) as VideoChannel
+ const { data } = await server.channels.list()
+ const videoChannelDeleted = data.find(a => a.name === 'Main user1 channel' && a.host === 'localhost:' + servers[0].port)
expect(videoChannelDeleted).to.be.undefined
}
})
it('Should not have video files', async () => {
for (const server of servers) {
- await checkVideoFilesWereRemoved(videoUUID, server.internalServerNumber)
+ await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
}
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import {
- cleanupTests,
- flushAndRunServer,
- getMyUserInformation,
- getUserInformation,
- login,
- registerUser,
- ServerInfo,
- updateCustomSubConfig,
- updateMyUser,
- userLogin,
- verifyEmail
-} from '../../../../shared/extra-utils'
-import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
-import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { User } from '../../../../shared/models/users'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+import * as chai from 'chai'
+import { cleanupTests, createSingleServer, MockSmtpServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
const expect = chai.expect
describe('Test users account verification', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userId: number
let userAccessToken: string
let verificationString: string
port
}
}
- server = await flushAndRunServer(1, overrideConfig)
+ server = await createSingleServer(1, overrideConfig)
await setAccessTokensToServers([ server ])
})
it('Should register user and send verification email if verification required', async function () {
this.timeout(30000)
- await updateCustomSubConfig(server.url, server.accessToken, {
- signup: {
- enabled: true,
- requiresEmailVerification: true,
- limit: 10
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ signup: {
+ enabled: true,
+ requiresEmailVerification: true,
+ limit: 10
+ }
}
})
- await registerUser(server.url, user1.username, user1.password)
+ await server.users.register(user1)
await waitJobs(server)
expectedEmailsLength++
userId = parseInt(userIdMatches[1], 10)
- const resUserInfo = await getUserInformation(server.url, server.accessToken, userId)
- expect(resUserInfo.body.emailVerified).to.be.false
+ const body = await server.users.get({ userId })
+ expect(body.emailVerified).to.be.false
})
it('Should not allow login for user with unverified email', async function () {
- const resLogin = await login(server.url, server.client, user1, HttpStatusCode.BAD_REQUEST_400)
- expect(resLogin.body.detail).to.contain('User email is not verified.')
+ const { detail } = await server.login.login({ user: user1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ expect(detail).to.contain('User email is not verified.')
})
it('Should verify the user via email and allow login', async function () {
- await verifyEmail(server.url, userId, verificationString)
+ await server.users.verifyEmail({ userId, verificationString })
- const res = await login(server.url, server.client, user1)
- userAccessToken = res.body.access_token
+ const body = await server.login.login({ user: user1 })
+ userAccessToken = body.access_token
- const resUserVerified = await getUserInformation(server.url, server.accessToken, userId)
- expect(resUserVerified.body.emailVerified).to.be.true
+ const user = await server.users.get({ userId })
+ expect(user.emailVerified).to.be.true
})
it('Should be able to change the user email', async function () {
let updateVerificationString: string
{
- await updateMyUser({
- url: server.url,
- accessToken: userAccessToken,
+ await server.users.updateMe({
+ token: userAccessToken,
email: 'updated@example.com',
currentPassword: user1.password
})
}
{
- const res = await getMyUserInformation(server.url, userAccessToken)
- const me: User = res.body
-
+ const me = await server.users.getMyInfo({ token: userAccessToken })
expect(me.email).to.equal('user_1@example.com')
expect(me.pendingEmail).to.equal('updated@example.com')
}
{
- await verifyEmail(server.url, userId, updateVerificationString, true)
-
- const res = await getMyUserInformation(server.url, userAccessToken)
- const me: User = res.body
+ await server.users.verifyEmail({ userId, verificationString: updateVerificationString, isPendingEmail: true })
+ const me = await server.users.getMyInfo({ token: userAccessToken })
expect(me.email).to.equal('updated@example.com')
expect(me.pendingEmail).to.be.null
}
it('Should register user not requiring email verification if setting not enabled', async function () {
this.timeout(5000)
- await updateCustomSubConfig(server.url, server.accessToken, {
- signup: {
- enabled: true,
- requiresEmailVerification: false,
- limit: 10
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ signup: {
+ enabled: true,
+ requiresEmailVerification: false,
+ limit: 10
+ }
}
})
- await registerUser(server.url, user2.username, user2.password)
+ await server.users.register(user2)
await waitJobs(server)
expect(emails).to.have.lengthOf(expectedEmailsLength)
- const accessToken = await userLogin(server, user2)
+ const accessToken = await server.login.getAccessToken(user2)
- const resMyUserInfo = await getMyUserInformation(server.url, accessToken)
- expect(resMyUserInfo.body.emailVerified).to.be.null
+ const user = await server.users.getMyInfo({ token: accessToken })
+ expect(user.emailVerified).to.be.null
})
it('Should allow login for user with unverified email when setting later enabled', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
- signup: {
- enabled: true,
- requiresEmailVerification: true,
- limit: 10
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ signup: {
+ enabled: true,
+ requiresEmailVerification: true,
+ limit: 10
+ }
}
})
- await userLogin(server, user2)
+ await server.login.getAccessToken(user2)
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
-import { AbuseState, AbuseUpdate, MyUser, User, UserRole, Video, VideoPlaylistType } from '@shared/models'
-import { CustomConfig, OAuth2ErrorCode } from '@shared/models/server'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoCommentThread,
- blockUser,
cleanupTests,
- closeAllSequelize,
- createUser,
- deleteMe,
- flushAndRunServer,
- getAccountRatings,
- getAdminAbusesList,
- getBlacklistedVideosList,
- getCustomConfig,
- getMyUserInformation,
- getMyUserVideoQuotaUsed,
- getMyUserVideoRating,
- getUserInformation,
- getUsersList,
- getUsersListPaginationAndSort,
- getVideoChannel,
- getVideosList,
- installPlugin,
+ createSingleServer,
killallServers,
- login,
makePutBodyRequest,
- rateVideo,
- registerUserWithChannel,
- removeUser,
- removeVideo,
- reportAbuse,
- reRunServer,
- ServerInfo,
- setTokenField,
+ PeerTubeServer,
+ setAccessTokensToServers,
testImage,
- unblockUser,
- updateAbuse,
- updateCustomSubConfig,
- updateMyAvatar,
- updateMyUser,
- updateUser,
- uploadVideo,
- userLogin,
waitJobs
-} from '../../../../shared/extra-utils'
-import { follow } from '../../../../shared/extra-utils/server/follows'
-import { logout, refreshToken, setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
-import { getMyVideos } from '../../../../shared/extra-utils/videos/videos'
-import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
+} from '@shared/extra-utils'
+import { AbuseState, HttpStatusCode, OAuth2ErrorCode, UserAdminFlag, UserRole, Video, VideoPlaylistType } from '@shared/models'
const expect = chai.expect
describe('Test users', function () {
- let server: ServerInfo
- let accessToken: string
- let accessTokenUser: string
+ let server: PeerTubeServer
+ let token: string
+ let userToken: string
let videoId: number
let userId: number
const user = {
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1, {
+ server = await createSingleServer(1, {
rates_limit: {
login: {
max: 30
await setAccessTokensToServers([ server ])
- await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-theme-background-red' })
+ await server.plugins.install({ npmName: 'peertube-theme-background-red' })
})
describe('OAuth client', function () {
it('Should remove the last client')
it('Should not login with an invalid client id', async function () {
- const client = { id: 'client', secret: server.client.secret }
- const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400)
+ const client = { id: 'client', secret: server.store.client.secret }
+ const body = await server.login.login({ client, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- expect(res.body.code).to.equal(OAuth2ErrorCode.INVALID_CLIENT)
- expect(res.body.error).to.contain('client is invalid')
- expect(res.body.type.startsWith('https://')).to.be.true
- expect(res.body.type).to.contain(OAuth2ErrorCode.INVALID_CLIENT)
+ expect(body.code).to.equal(OAuth2ErrorCode.INVALID_CLIENT)
+ expect(body.error).to.contain('client is invalid')
+ expect(body.type.startsWith('https://')).to.be.true
+ expect(body.type).to.contain(OAuth2ErrorCode.INVALID_CLIENT)
})
it('Should not login with an invalid client secret', async function () {
- const client = { id: server.client.id, secret: 'coucou' }
- const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400)
+ const client = { id: server.store.client.id, secret: 'coucou' }
+ const body = await server.login.login({ client, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- expect(res.body.code).to.equal(OAuth2ErrorCode.INVALID_CLIENT)
- expect(res.body.error).to.contain('client is invalid')
- expect(res.body.type.startsWith('https://')).to.be.true
- expect(res.body.type).to.contain(OAuth2ErrorCode.INVALID_CLIENT)
+ expect(body.code).to.equal(OAuth2ErrorCode.INVALID_CLIENT)
+ expect(body.error).to.contain('client is invalid')
+ expect(body.type.startsWith('https://')).to.be.true
+ expect(body.type).to.contain(OAuth2ErrorCode.INVALID_CLIENT)
})
})
describe('Login', function () {
it('Should not login with an invalid username', async function () {
- const user = { username: 'captain crochet', password: server.user.password }
- const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400)
+ const user = { username: 'captain crochet', password: server.store.user.password }
+ const body = await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- expect(res.body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
- expect(res.body.error).to.contain('credentials are invalid')
- expect(res.body.type.startsWith('https://')).to.be.true
- expect(res.body.type).to.contain(OAuth2ErrorCode.INVALID_GRANT)
+ expect(body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
+ expect(body.error).to.contain('credentials are invalid')
+ expect(body.type.startsWith('https://')).to.be.true
+ expect(body.type).to.contain(OAuth2ErrorCode.INVALID_GRANT)
})
it('Should not login with an invalid password', async function () {
- const user = { username: server.user.username, password: 'mew_three' }
- const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400)
+ const user = { username: server.store.user.username, password: 'mew_three' }
+ const body = await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- expect(res.body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
- expect(res.body.error).to.contain('credentials are invalid')
- expect(res.body.type.startsWith('https://')).to.be.true
- expect(res.body.type).to.contain(OAuth2ErrorCode.INVALID_GRANT)
+ expect(body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
+ expect(body.error).to.contain('credentials are invalid')
+ expect(body.type.startsWith('https://')).to.be.true
+ expect(body.type).to.contain(OAuth2ErrorCode.INVALID_GRANT)
})
it('Should not be able to upload a video', async function () {
- accessToken = 'my_super_token'
+ token = 'my_super_token'
- const videoAttributes = {}
- await uploadVideo(server.url, accessToken, videoAttributes, HttpStatusCode.UNAUTHORIZED_401)
+ await server.videos.upload({ token, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to follow', async function () {
- accessToken = 'my_super_token'
- await follow(server.url, [ 'http://example.com' ], accessToken, HttpStatusCode.UNAUTHORIZED_401)
+ token = 'my_super_token'
+
+ await server.follows.follow({
+ hosts: [ 'http://example.com' ],
+ token,
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
+ })
})
it('Should not be able to unfollow')
it('Should be able to login', async function () {
- const res = await login(server.url, server.client, server.user, HttpStatusCode.OK_200)
+ const body = await server.login.login({ expectedStatus: HttpStatusCode.OK_200 })
- accessToken = res.body.access_token
+ token = body.access_token
})
it('Should be able to login with an insensitive username', async function () {
- const user = { username: 'RoOt', password: server.user.password }
- await login(server.url, server.client, user, HttpStatusCode.OK_200)
+ const user = { username: 'RoOt', password: server.store.user.password }
+ await server.login.login({ user, expectedStatus: HttpStatusCode.OK_200 })
- const user2 = { username: 'rOoT', password: server.user.password }
- await login(server.url, server.client, user2, HttpStatusCode.OK_200)
+ const user2 = { username: 'rOoT', password: server.store.user.password }
+ await server.login.login({ user: user2, expectedStatus: HttpStatusCode.OK_200 })
- const user3 = { username: 'ROOt', password: server.user.password }
- await login(server.url, server.client, user3, HttpStatusCode.OK_200)
+ const user3 = { username: 'ROOt', password: server.store.user.password }
+ await server.login.login({ user: user3, expectedStatus: HttpStatusCode.OK_200 })
})
})
describe('Upload', function () {
it('Should upload the video with the correct token', async function () {
- const videoAttributes = {}
- await uploadVideo(server.url, accessToken, videoAttributes)
- const res = await getVideosList(server.url)
- const video = res.body.data[0]
+ await server.videos.upload({ token })
+ const { data } = await server.videos.list()
+ const video = data[0]
expect(video.account.name).to.equal('root')
videoId = video.id
})
it('Should upload the video again with the correct token', async function () {
- const videoAttributes = {}
- await uploadVideo(server.url, accessToken, videoAttributes)
+ await server.videos.upload({ token })
})
})
describe('Ratings', function () {
it('Should retrieve a video rating', async function () {
- await rateVideo(server.url, accessToken, videoId, 'like')
- const res = await getMyUserVideoRating(server.url, accessToken, videoId)
- const rating = res.body
+ await server.videos.rate({ id: videoId, rating: 'like' })
+ const rating = await server.users.getMyRating({ token, videoId })
expect(rating.videoId).to.equal(videoId)
expect(rating.rating).to.equal('like')
})
it('Should retrieve ratings list', async function () {
- await rateVideo(server.url, accessToken, videoId, 'like')
+ await server.videos.rate({ id: videoId, rating: 'like' })
- const res = await getAccountRatings(server.url, server.user.username, server.accessToken, null, HttpStatusCode.OK_200)
- const ratings = res.body
+ const body = await server.accounts.listRatings({ accountName: server.store.user.username })
- expect(ratings.total).to.equal(1)
- expect(ratings.data[0].video.id).to.equal(videoId)
- expect(ratings.data[0].rating).to.equal('like')
+ expect(body.total).to.equal(1)
+ expect(body.data[0].video.id).to.equal(videoId)
+ expect(body.data[0].rating).to.equal('like')
})
it('Should retrieve ratings list by rating type', async function () {
{
- const res = await getAccountRatings(server.url, server.user.username, server.accessToken, 'like')
- const ratings = res.body
- expect(ratings.data.length).to.equal(1)
+ const body = await server.accounts.listRatings({ accountName: server.store.user.username, rating: 'like' })
+ expect(body.data.length).to.equal(1)
}
{
- const res = await getAccountRatings(server.url, server.user.username, server.accessToken, 'dislike')
- const ratings = res.body
- expect(ratings.data.length).to.equal(0)
+ const body = await server.accounts.listRatings({ accountName: server.store.user.username, rating: 'dislike' })
+ expect(body.data.length).to.equal(0)
}
})
})
describe('Remove video', function () {
it('Should not be able to remove the video with an incorrect token', async function () {
- await removeVideo(server.url, 'bad_token', videoId, HttpStatusCode.UNAUTHORIZED_401)
+ await server.videos.remove({ token: 'bad_token', id: videoId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to remove the video with the token of another account')
it('Should be able to remove the video with the correct token', async function () {
- await removeVideo(server.url, accessToken, videoId)
+ await server.videos.remove({ token, id: videoId })
})
})
describe('Logout', function () {
it('Should logout (revoke token)', async function () {
- await logout(server.url, server.accessToken)
+ await server.login.logout({ token: server.accessToken })
})
it('Should not be able to get the user information', async function () {
- await getMyUserInformation(server.url, server.accessToken, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyInfo({ expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to upload a video', async function () {
- await uploadVideo(server.url, server.accessToken, { name: 'video' }, HttpStatusCode.UNAUTHORIZED_401)
+ await server.videos.upload({ attributes: { name: 'video' }, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to rate a video', async function () {
path: path + videoId,
token: 'wrong token',
fields: data,
- statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
+ expectedStatus: HttpStatusCode.UNAUTHORIZED_401
}
await makePutBodyRequest(options)
})
it('Should be able to login again', async function () {
- const res = await login(server.url, server.client, server.user)
- server.accessToken = res.body.access_token
- server.refreshToken = res.body.refresh_token
+ const body = await server.login.login()
+ server.accessToken = body.access_token
+ server.refreshToken = body.refresh_token
})
it('Should be able to get my user information again', async function () {
- await getMyUserInformation(server.url, server.accessToken)
+ await server.users.getMyInfo()
})
it('Should have an expired access token', async function () {
this.timeout(15000)
- await setTokenField(server.internalServerNumber, server.accessToken, 'accessTokenExpiresAt', new Date().toISOString())
- await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString())
+ await server.sql.setTokenField(server.accessToken, 'accessTokenExpiresAt', new Date().toISOString())
+ await server.sql.setTokenField(server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString())
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
- await getMyUserInformation(server.url, server.accessToken, 401)
+ await server.users.getMyInfo({ expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to refresh an access token with an expired refresh token', async function () {
- await refreshToken(server, server.refreshToken, 400)
+ await server.login.refreshToken({ refreshToken: server.refreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should refresh the token', async function () {
this.timeout(15000)
const futureDate = new Date(new Date().getTime() + 1000 * 60).toISOString()
- await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', futureDate)
+ await server.sql.setTokenField(server.accessToken, 'refreshTokenExpiresAt', futureDate)
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
- const res = await refreshToken(server, server.refreshToken)
+ const res = await server.login.refreshToken({ refreshToken: server.refreshToken })
server.accessToken = res.body.access_token
server.refreshToken = res.body.refresh_token
})
it('Should be able to get my user information again', async function () {
- await getMyUserInformation(server.url, server.accessToken)
+ await server.users.getMyInfo()
})
})
describe('Creating a user', function () {
it('Should be able to create a new user', async function () {
- await createUser({
- url: server.url,
- accessToken: accessToken,
- username: user.username,
- password: user.password,
- videoQuota: 2 * 1024 * 1024,
- adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
- })
+ await server.users.create({ ...user, videoQuota: 2 * 1024 * 1024, adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST })
})
it('Should be able to login with this user', async function () {
- accessTokenUser = await userLogin(server, user)
+ userToken = await server.login.getAccessToken(user)
})
it('Should be able to get user information', async function () {
- const res1 = await getMyUserInformation(server.url, accessTokenUser)
- const userMe: MyUser = res1.body
+ const userMe = await server.users.getMyInfo({ token: userToken })
- const res2 = await getUserInformation(server.url, server.accessToken, userMe.id, true)
- const userGet: User = res2.body
+ const userGet = await server.users.get({ userId: userMe.id, withStats: true })
for (const user of [ userMe, userGet ]) {
expect(user.username).to.equal('user_1')
it('Should be able to upload a video with this user', async function () {
this.timeout(10000)
- const videoAttributes = {
+ const attributes = {
name: 'super user video',
fixture: 'video_short.webm'
}
- await uploadVideo(server.url, accessTokenUser, videoAttributes)
+ await server.videos.upload({ token: userToken, attributes })
})
it('Should have video quota updated', async function () {
- const res = await getMyUserVideoQuotaUsed(server.url, accessTokenUser)
- const data = res.body
-
- expect(data.videoQuotaUsed).to.equal(218910)
-
- const resUsers = await getUsersList(server.url, server.accessToken)
+ const quota = await server.users.getMyQuotaUsed({ token: userToken })
+ expect(quota.videoQuotaUsed).to.equal(218910)
- const users: User[] = resUsers.body.data
- const tmpUser = users.find(u => u.username === user.username)
+ const { data } = await server.users.list()
+ const tmpUser = data.find(u => u.username === user.username)
expect(tmpUser.videoQuotaUsed).to.equal(218910)
})
it('Should be able to list my videos', async function () {
- const res = await getMyVideos(server.url, accessTokenUser, 0, 5)
- expect(res.body.total).to.equal(1)
+ const { total, data } = await server.videos.listMyVideos({ token: userToken })
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(1)
-
- const video: Video = videos[0]
+ const video: Video = data[0]
expect(video.name).to.equal('super user video')
expect(video.thumbnailPath).to.not.be.null
expect(video.previewPath).to.not.be.null
it('Should be able to search in my videos', async function () {
{
- const res = await getMyVideos(server.url, accessTokenUser, 0, 5, '-createdAt', 'user video')
- expect(res.body.total).to.equal(1)
-
- const videos = res.body.data
- expect(videos).to.have.lengthOf(1)
+ const { total, data } = await server.videos.listMyVideos({ token: userToken, sort: '-createdAt', search: 'user video' })
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
}
{
- const res = await getMyVideos(server.url, accessTokenUser, 0, 5, '-createdAt', 'toto')
- expect(res.body.total).to.equal(0)
-
- const videos = res.body.data
- expect(videos).to.have.lengthOf(0)
+ const { total, data } = await server.videos.listMyVideos({ token: userToken, sort: '-createdAt', search: 'toto' })
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
}
})
this.timeout(60000)
{
- const res = await getCustomConfig(server.url, server.accessToken)
- const config = res.body as CustomConfig
+ const config = await server.config.getCustomConfig()
config.transcoding.webtorrent.enabled = false
config.transcoding.hls.enabled = true
config.transcoding.enabled = true
- await updateCustomSubConfig(server.url, server.accessToken, config)
+ await server.config.updateCustomSubConfig({ newConfig: config })
}
{
- const videoAttributes = {
+ const attributes = {
name: 'super user video 2',
fixture: 'video_short.webm'
}
- await uploadVideo(server.url, accessTokenUser, videoAttributes)
+ await server.videos.upload({ token: userToken, attributes })
await waitJobs([ server ])
}
{
- const res = await getMyUserVideoQuotaUsed(server.url, accessTokenUser)
- const data = res.body
-
+ const data = await server.users.getMyQuotaUsed({ token: userToken })
expect(data.videoQuotaUsed).to.be.greaterThan(220000)
}
})
describe('Users listing', function () {
it('Should list all the users', async function () {
- const res = await getUsersList(server.url, server.accessToken)
- const result = res.body
- const total = result.total
- const users = result.data
+ const { data, total } = await server.users.list()
expect(total).to.equal(2)
- expect(users).to.be.an('array')
- expect(users.length).to.equal(2)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(2)
- const user = users[0]
+ const user = data[0]
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('user_1@example.com')
expect(user.nsfwPolicy).to.equal('display')
- const rootUser = users[1]
+ const rootUser = data[1]
expect(rootUser.username).to.equal('root')
expect(rootUser.email).to.equal('admin' + server.internalServerNumber + '@example.com')
expect(user.nsfwPolicy).to.equal('display')
})
it('Should list only the first user by username asc', async function () {
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, 'username')
-
- const result = res.body
- const total = result.total
- const users = result.data
+ const { total, data } = await server.users.list({ start: 0, count: 1, sort: 'username' })
expect(total).to.equal(2)
- expect(users.length).to.equal(1)
+ expect(data.length).to.equal(1)
- const user = users[0]
+ const user = data[0]
expect(user.username).to.equal('root')
expect(user.email).to.equal('admin' + server.internalServerNumber + '@example.com')
expect(user.roleLabel).to.equal('Administrator')
})
it('Should list only the first user by username desc', async function () {
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, '-username')
- const result = res.body
- const total = result.total
- const users = result.data
+ const { total, data } = await server.users.list({ start: 0, count: 1, sort: '-username' })
expect(total).to.equal(2)
- expect(users.length).to.equal(1)
+ expect(data.length).to.equal(1)
- const user = users[0]
+ const user = data[0]
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('user_1@example.com')
expect(user.nsfwPolicy).to.equal('display')
})
it('Should list only the second user by createdAt desc', async function () {
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, '-createdAt')
- const result = res.body
- const total = result.total
- const users = result.data
-
+ const { data, total } = await server.users.list({ start: 0, count: 1, sort: '-createdAt' })
expect(total).to.equal(2)
- expect(users.length).to.equal(1)
- const user = users[0]
+ expect(data.length).to.equal(1)
+
+ const user = data[0]
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('user_1@example.com')
expect(user.nsfwPolicy).to.equal('display')
})
it('Should list all the users by createdAt asc', async function () {
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt')
- const result = res.body
- const total = result.total
- const users = result.data
+ const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt' })
expect(total).to.equal(2)
- expect(users.length).to.equal(2)
+ expect(data.length).to.equal(2)
- expect(users[0].username).to.equal('root')
- expect(users[0].email).to.equal('admin' + server.internalServerNumber + '@example.com')
- expect(users[0].nsfwPolicy).to.equal('display')
+ expect(data[0].username).to.equal('root')
+ expect(data[0].email).to.equal('admin' + server.internalServerNumber + '@example.com')
+ expect(data[0].nsfwPolicy).to.equal('display')
- expect(users[1].username).to.equal('user_1')
- expect(users[1].email).to.equal('user_1@example.com')
- expect(users[1].nsfwPolicy).to.equal('display')
+ expect(data[1].username).to.equal('user_1')
+ expect(data[1].email).to.equal('user_1@example.com')
+ expect(data[1].nsfwPolicy).to.equal('display')
})
it('Should search user by username', async function () {
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'oot')
- const users = res.body.data as User[]
-
- expect(res.body.total).to.equal(1)
- expect(users.length).to.equal(1)
-
- expect(users[0].username).to.equal('root')
+ const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'oot' })
+ expect(total).to.equal(1)
+ expect(data.length).to.equal(1)
+ expect(data[0].username).to.equal('root')
})
it('Should search user by email', async function () {
{
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'r_1@exam')
- const users = res.body.data as User[]
-
- expect(res.body.total).to.equal(1)
- expect(users.length).to.equal(1)
-
- expect(users[0].username).to.equal('user_1')
- expect(users[0].email).to.equal('user_1@example.com')
+ const { total, data } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'r_1@exam' })
+ expect(total).to.equal(1)
+ expect(data.length).to.equal(1)
+ expect(data[0].username).to.equal('user_1')
+ expect(data[0].email).to.equal('user_1@example.com')
}
{
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'example')
- const users = res.body.data as User[]
-
- expect(res.body.total).to.equal(2)
- expect(users.length).to.equal(2)
-
- expect(users[0].username).to.equal('root')
- expect(users[1].username).to.equal('user_1')
+ const { total, data } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'example' })
+ expect(total).to.equal(2)
+ expect(data.length).to.equal(2)
+ expect(data[0].username).to.equal('root')
+ expect(data[1].username).to.equal('user_1')
}
})
})
describe('Update my account', function () {
+
it('Should update my password', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
currentPassword: 'super password',
password: 'new password'
})
user.password = 'new password'
- await userLogin(server, user, HttpStatusCode.OK_200)
+ await server.login.login({ user })
})
it('Should be able to change the NSFW display attribute', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
nsfwPolicy: 'do_not_list'
})
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
-
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('user_1@example.com')
expect(user.nsfwPolicy).to.equal('do_not_list')
})
it('Should be able to change the autoPlayVideo attribute', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
autoPlayVideo: false
})
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
-
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.autoPlayVideo).to.be.false
})
it('Should be able to change the autoPlayNextVideo attribute', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
autoPlayNextVideo: true
})
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
-
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.autoPlayNextVideo).to.be.true
})
it('Should be able to change the email attribute', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
currentPassword: 'new password',
email: 'updated@example.com'
})
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
-
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('updated@example.com')
expect(user.nsfwPolicy).to.equal('do_not_list')
it('Should be able to update my avatar with a gif', async function () {
const fixture = 'avatar.gif'
- await updateMyAvatar({
- url: server.url,
- accessToken: accessTokenUser,
- fixture
- })
-
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
+ await server.users.updateMyAvatar({ token: userToken, fixture })
+ const user = await server.users.getMyInfo({ token: userToken })
await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.gif')
})
for (const extension of [ '.png', '.gif' ]) {
const fixture = 'avatar' + extension
- await updateMyAvatar({
- url: server.url,
- accessToken: accessTokenUser,
- fixture
- })
-
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
+ await server.users.updateMyAvatar({ token: userToken, fixture })
+ const user = await server.users.getMyInfo({ token: userToken })
await testImage(server.url, 'avatar-resized', user.account.avatar.path, extension)
}
})
it('Should be able to update my display name', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
- displayName: 'new display name'
- })
-
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user = res.body
+ await server.users.updateMe({ token: userToken, displayName: 'new display name' })
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('updated@example.com')
expect(user.nsfwPolicy).to.equal('do_not_list')
})
it('Should be able to update my description', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
- description: 'my super description updated'
- })
-
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user: User = res.body
+ await server.users.updateMe({ token: userToken, description: 'my super description updated' })
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('updated@example.com')
expect(user.nsfwPolicy).to.equal('do_not_list')
it('Should be able to update my theme', async function () {
for (const theme of [ 'background-red', 'default', 'instance-default' ]) {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
- theme
- })
+ await server.users.updateMe({ token: userToken, theme })
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const body: User = res.body
-
- expect(body.theme).to.equal(theme)
+ const user = await server.users.getMyInfo({ token: userToken })
+ expect(user.theme).to.equal(theme)
}
})
it('Should be able to update my modal preferences', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: accessTokenUser,
+ await server.users.updateMe({
+ token: userToken,
noInstanceConfigWarningModal: true,
noWelcomeModal: true
})
- const res = await getMyUserInformation(server.url, accessTokenUser)
- const user: User = res.body
-
+ const user = await server.users.getMyInfo({ token: userToken })
expect(user.noWelcomeModal).to.be.true
expect(user.noInstanceConfigWarningModal).to.be.true
})
describe('Updating another user', function () {
it('Should be able to update another user', async function () {
- await updateUser({
- url: server.url,
+ await server.users.update({
userId,
- accessToken,
+ token,
email: 'updated2@example.com',
emailVerified: true,
videoQuota: 42,
pluginAuth: 'toto'
})
- const res = await getUserInformation(server.url, accessToken, userId)
- const user = res.body as User
+ const user = await server.users.get({ token, userId })
expect(user.username).to.equal('user_1')
expect(user.email).to.equal('updated2@example.com')
})
it('Should reset the auth plugin', async function () {
- await updateUser({ url: server.url, userId, accessToken, pluginAuth: null })
+ await server.users.update({ userId, token, pluginAuth: null })
- const res = await getUserInformation(server.url, accessToken, userId)
- const user = res.body as User
+ const user = await server.users.get({ token, userId })
expect(user.pluginAuth).to.be.null
})
it('Should have removed the user token', async function () {
- await getMyUserVideoQuotaUsed(server.url, accessTokenUser, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyQuotaUsed({ token: userToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- accessTokenUser = await userLogin(server, user)
+ userToken = await server.login.getAccessToken(user)
})
it('Should be able to update another user password', async function () {
- await updateUser({
- url: server.url,
- userId,
- accessToken,
- password: 'password updated'
- })
+ await server.users.update({ userId, token, password: 'password updated' })
- await getMyUserVideoQuotaUsed(server.url, accessTokenUser, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyQuotaUsed({ token: userToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
user.password = 'password updated'
- accessTokenUser = await userLogin(server, user)
+ userToken = await server.login.getAccessToken(user)
})
})
describe('Video blacklists', function () {
it('Should be able to list video blacklist by a moderator', async function () {
- await getBlacklistedVideosList({ url: server.url, token: accessTokenUser })
+ await server.blacklist.list({ token: userToken })
})
})
describe('Remove a user', function () {
it('Should be able to remove this user', async function () {
- await removeUser(server.url, userId, accessToken)
+ await server.users.remove({ userId, token })
})
it('Should not be able to login with this user', async function () {
- await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not have videos of this user', async function () {
- const res = await getVideosList(server.url)
-
- expect(res.body.total).to.equal(1)
+ const { data, total } = await server.videos.list()
+ expect(total).to.equal(1)
- const video = res.body.data[0]
+ const video = data[0]
expect(video.account.name).to.equal('root')
})
})
const user = { displayName: 'super user 15', username: 'user_15', password: 'my super password' }
const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' }
- await registerUserWithChannel({ url: server.url, user, channel })
+ await server.users.register({ ...user, channel })
})
it('Should be able to login with this registered user', async function () {
password: 'my super password'
}
- user15AccessToken = await userLogin(server, user15)
+ user15AccessToken = await server.login.getAccessToken(user15)
})
it('Should have the correct display name', async function () {
- const res = await getMyUserInformation(server.url, user15AccessToken)
- const user: User = res.body
-
+ const user = await server.users.getMyInfo({ token: user15AccessToken })
expect(user.account.displayName).to.equal('super user 15')
})
it('Should have the correct video quota', async function () {
- const res = await getMyUserInformation(server.url, user15AccessToken)
- const user = res.body
-
+ const user = await server.users.getMyInfo({ token: user15AccessToken })
expect(user.videoQuota).to.equal(5 * 1024 * 1024)
})
it('Should have created the channel', async function () {
- const res = await getVideoChannel(server.url, 'my_user_15_channel')
+ const { displayName } = await server.channels.get({ channelName: 'my_user_15_channel' })
- expect(res.body.displayName).to.equal('my channel rocks')
+ expect(displayName).to.equal('my channel rocks')
})
it('Should remove me', async function () {
{
- const res = await getUsersList(server.url, server.accessToken)
- expect(res.body.data.find(u => u.username === 'user_15')).to.not.be.undefined
+ const { data } = await server.users.list()
+ expect(data.find(u => u.username === 'user_15')).to.not.be.undefined
}
- await deleteMe(server.url, user15AccessToken)
+ await server.users.deleteMe({ token: user15AccessToken })
{
- const res = await getUsersList(server.url, server.accessToken)
- expect(res.body.data.find(u => u.username === 'user_15')).to.be.undefined
+ const { data } = await server.users.list()
+ expect(data.find(u => u.username === 'user_15')).to.be.undefined
}
})
})
}
it('Should block a user', async function () {
- const resUser = await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: user16.username,
- password: user16.password
- })
- user16Id = resUser.body.user.id
+ const user = await server.users.create({ ...user16 })
+ user16Id = user.id
- user16AccessToken = await userLogin(server, user16)
+ user16AccessToken = await server.login.getAccessToken(user16)
- await getMyUserInformation(server.url, user16AccessToken, HttpStatusCode.OK_200)
- await blockUser(server.url, user16Id, server.accessToken)
+ await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.OK_200 })
+ await server.users.banUser({ userId: user16Id })
- await getMyUserInformation(server.url, user16AccessToken, HttpStatusCode.UNAUTHORIZED_401)
- await userLogin(server, user16, HttpStatusCode.BAD_REQUEST_400)
+ await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await server.login.login({ user: user16, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should search user by banned status', async function () {
{
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', undefined, true)
- const users = res.body.data as User[]
+ const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', blocked: true })
+ expect(total).to.equal(1)
+ expect(data.length).to.equal(1)
- expect(res.body.total).to.equal(1)
- expect(users.length).to.equal(1)
-
- expect(users[0].username).to.equal(user16.username)
+ expect(data[0].username).to.equal(user16.username)
}
{
- const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', undefined, false)
- const users = res.body.data as User[]
-
- expect(res.body.total).to.equal(1)
- expect(users.length).to.equal(1)
+ const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', blocked: false })
+ expect(total).to.equal(1)
+ expect(data.length).to.equal(1)
- expect(users[0].username).to.not.equal(user16.username)
+ expect(data[0].username).to.not.equal(user16.username)
}
})
it('Should unblock a user', async function () {
- await unblockUser(server.url, user16Id, server.accessToken)
- user16AccessToken = await userLogin(server, user16)
- await getMyUserInformation(server.url, user16AccessToken, HttpStatusCode.OK_200)
+ await server.users.unbanUser({ userId: user16Id })
+ user16AccessToken = await server.login.getAccessToken(user16)
+ await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.OK_200 })
})
})
username: 'user_17',
password: 'my super password'
}
- const resUser = await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: user17.username,
- password: user17.password
- })
+ const created = await server.users.create({ ...user17 })
- user17Id = resUser.body.user.id
- user17AccessToken = await userLogin(server, user17)
-
- const res = await getUserInformation(server.url, server.accessToken, user17Id, true)
- const user: User = res.body
+ user17Id = created.id
+ user17AccessToken = await server.login.getAccessToken(user17)
+ const user = await server.users.get({ userId: user17Id, withStats: true })
expect(user.videosCount).to.equal(0)
expect(user.videoCommentsCount).to.equal(0)
expect(user.abusesCount).to.equal(0)
})
it('Should report correct videos count', async function () {
- const videoAttributes = {
- name: 'video to test user stats'
- }
- await uploadVideo(server.url, user17AccessToken, videoAttributes)
- const res1 = await getVideosList(server.url)
- videoId = res1.body.data.find(video => video.name === videoAttributes.name).id
+ const attributes = { name: 'video to test user stats' }
+ await server.videos.upload({ token: user17AccessToken, attributes })
- const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
- const user: User = res2.body
+ const { data } = await server.videos.list()
+ videoId = data.find(video => video.name === attributes.name).id
+ const user = await server.users.get({ userId: user17Id, withStats: true })
expect(user.videosCount).to.equal(1)
})
it('Should report correct video comments for user', async function () {
const text = 'super comment'
- await addVideoCommentThread(server.url, user17AccessToken, videoId, text)
-
- const res = await getUserInformation(server.url, server.accessToken, user17Id, true)
- const user: User = res.body
+ await server.comments.createThread({ token: user17AccessToken, videoId, text })
+ const user = await server.users.get({ userId: user17Id, withStats: true })
expect(user.videoCommentsCount).to.equal(1)
})
it('Should report correct abuses counts', async function () {
const reason = 'my super bad reason'
- await reportAbuse({ url: server.url, token: user17AccessToken, videoId, reason })
-
- const res1 = await getAdminAbusesList({ url: server.url, token: server.accessToken })
- const abuseId = res1.body.data[0].id
+ await server.abuses.report({ token: user17AccessToken, videoId, reason })
- const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
- const user2: User = res2.body
+ const body1 = await server.abuses.getAdminList()
+ const abuseId = body1.data[0].id
+ const user2 = await server.users.get({ userId: user17Id, withStats: true })
expect(user2.abusesCount).to.equal(1) // number of incriminations
expect(user2.abusesCreatedCount).to.equal(1) // number of reports created
- const body: AbuseUpdate = { state: AbuseState.ACCEPTED }
- await updateAbuse(server.url, server.accessToken, abuseId, body)
-
- const res3 = await getUserInformation(server.url, server.accessToken, user17Id, true)
- const user3: User = res3.body
+ await server.abuses.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
+ const user3 = await server.users.get({ userId: user17Id, withStats: true })
expect(user3.abusesAcceptedCount).to.equal(1) // number of reports created accepted
})
})
after(async function () {
- await closeAllSequelize([ server ])
await cleanupTests([ server ])
})
})
import 'mocha'
import * as chai from 'chai'
-import { join } from 'path'
import { getAudioStream, getVideoStreamSize } from '@server/helpers/ffprobe-utils'
-import {
- buildServerDirectory,
- cleanupTests,
- doubleFollow,
- flushAndRunMultipleServers,
- getVideo,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo,
- waitJobs
-} from '../../../../shared/extra-utils'
-import { VideoDetails } from '../../../../shared/models/videos'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
const expect = chai.expect
describe('Test audio only video transcoding', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID: string
+ let webtorrentAudioFileUrl: string
+ let fragmentedAudioFileUrl: string
before(async function () {
this.timeout(120000)
}
}
}
- servers = await flushAndRunMultipleServers(2, configOverride)
+ servers = await createMultipleServers(2, configOverride)
// Get the access tokens
await setAccessTokensToServers(servers)
it('Should upload a video and transcode it', async function () {
this.timeout(120000)
- const resUpload = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'audio only' })
- videoUUID = resUpload.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'audio only' } })
+ videoUUID = uuid
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
-
+ const video = await server.videos.get({ id: videoUUID })
expect(video.streamingPlaylists).to.have.lengthOf(1)
for (const files of [ video.files, video.streamingPlaylists[0].files ]) {
expect(files[1].resolution.id).to.equal(240)
expect(files[2].resolution.id).to.equal(0)
}
+
+ if (server.serverNumber === 1) {
+ webtorrentAudioFileUrl = video.files[2].fileUrl
+ fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl
+ }
}
})
it('0p transcoded video should not have video', async function () {
const paths = [
- buildServerDirectory(servers[0], join('videos', videoUUID + '-0.mp4')),
- buildServerDirectory(servers[0], join('streaming-playlists', 'hls', videoUUID, videoUUID + '-0-fragmented.mp4'))
+ servers[0].servers.buildWebTorrentFilePath(webtorrentAudioFileUrl),
+ servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl)
]
for (const path of paths) {
import 'mocha'
import * as chai from 'chai'
import * as request from 'supertest'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoChannel,
buildAbsoluteFixturePath,
checkTmpIsEmpty,
checkVideoFilesWereRemoved,
cleanupTests,
completeVideoCheck,
- createUser,
+ createMultipleServers,
dateIsValid,
doubleFollow,
- flushAndRunMultipleServers,
- getLocalVideos,
- getVideo,
- getVideoChannelsList,
- getVideosList,
- rateVideo,
- removeVideo,
- ServerInfo,
+ PeerTubeServer,
+ saveVideoInServers,
setAccessTokensToServers,
testImage,
- updateVideo,
- uploadVideo,
- userLogin,
- viewVideo,
wait,
+ waitJobs,
webtorrentAdd
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- addVideoCommentReply,
- addVideoCommentThread,
- deleteVideoComment,
- findCommentId,
- getVideoCommentThreads,
- getVideoThreadComments
-} from '../../../../shared/extra-utils/videos/video-comments'
-import { VideoComment, VideoCommentThreadTree, VideoPrivacy } from '../../../../shared/models/videos'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test multiple servers', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
const toRemove = []
let videoUUID = ''
let videoChannelId: number
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(3)
+ servers = await createMultipleServers(3)
// Get the access tokens
await setAccessTokensToServers(servers)
displayName: 'my channel',
description: 'super channel'
}
- await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
- const channelRes = await getVideoChannelsList(servers[0].url, 0, 1)
- videoChannelId = channelRes.body.data[0].id
+ await servers[0].channels.create({ attributes: videoChannel })
+ const { data } = await servers[0].channels.list({ start: 0, count: 1 })
+ videoChannelId = data[0].id
}
// Server 1 and server 2 follow each other
it('Should not have videos for all servers', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(0)
+ const { data } = await server.videos.list()
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(0)
}
})
it('Should upload the video on server 1 and propagate on each server', async function () {
this.timeout(25000)
- const videoAttributes = {
+ const attributes = {
name: 'my super name for server 1',
category: 5,
licence: 4,
channelId: videoChannelId,
fixture: 'video_short1.webm'
}
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ await servers[0].videos.upload({ attributes })
await waitJobs(servers)
]
}
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(1)
- const video = videos[0]
+ const { data } = await server.videos.list()
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(1)
+ const video = data[0]
- await completeVideoCheck(server.url, video, checkAttributes)
- publishedAt = video.publishedAt
+ await completeVideoCheck(server, video, checkAttributes)
+ publishedAt = video.publishedAt as string
}
})
username: 'user1',
password: 'super_password'
}
- await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
- const userAccessToken = await userLogin(servers[1], user)
+ await servers[1].users.create({ username: user.username, password: user.password })
+ const userAccessToken = await servers[1].login.getAccessToken(user)
- const videoAttributes = {
+ const attributes = {
name: 'my super name for server 2',
category: 4,
licence: 3,
thumbnailfile: 'thumbnail.jpg',
previewfile: 'preview.jpg'
}
- await uploadVideo(servers[1].url, userAccessToken, videoAttributes, HttpStatusCode.OK_200, 'resumable')
+ await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' })
// Transcoding
await waitJobs(servers)
previewfile: 'preview'
}
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(2)
- const video = videos[1]
+ const { data } = await server.videos.list()
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(2)
+ const video = data[1]
- await completeVideoCheck(server.url, video, checkAttributes)
+ await completeVideoCheck(server, video, checkAttributes)
}
})
it('Should upload two videos on server 3 and propagate on each server', async function () {
this.timeout(45000)
- const videoAttributes1 = {
- name: 'my super name for server 3',
- category: 6,
- licence: 5,
- language: 'de',
- nsfw: true,
- description: 'my super description for server 3',
- support: 'my super support text for server 3',
- tags: [ 'tag1p3' ],
- fixture: 'video_short3.webm'
+ {
+ const attributes = {
+ name: 'my super name for server 3',
+ category: 6,
+ licence: 5,
+ language: 'de',
+ nsfw: true,
+ description: 'my super description for server 3',
+ support: 'my super support text for server 3',
+ tags: [ 'tag1p3' ],
+ fixture: 'video_short3.webm'
+ }
+ await servers[2].videos.upload({ attributes })
}
- await uploadVideo(servers[2].url, servers[2].accessToken, videoAttributes1)
-
- const videoAttributes2 = {
- name: 'my super name for server 3-2',
- category: 7,
- licence: 6,
- language: 'ko',
- nsfw: false,
- description: 'my super description for server 3-2',
- support: 'my super support text for server 3-2',
- tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
- fixture: 'video_short.webm'
+
+ {
+ const attributes = {
+ name: 'my super name for server 3-2',
+ category: 7,
+ licence: 6,
+ language: 'ko',
+ nsfw: false,
+ description: 'my super description for server 3-2',
+ support: 'my super support text for server 3-2',
+ tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
+ fixture: 'video_short.webm'
+ }
+ await servers[2].videos.upload({ attributes })
}
- await uploadVideo(servers[2].url, servers[2].accessToken, videoAttributes2)
await waitJobs(servers)
// All servers should have this video
for (const server of servers) {
const isLocal = server.url === 'http://localhost:' + servers[2].port
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(4)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(4)
// We not sure about the order of the two last uploads
let video1 = null
let video2 = null
- if (videos[2].name === 'my super name for server 3') {
- video1 = videos[2]
- video2 = videos[3]
+ if (data[2].name === 'my super name for server 3') {
+ video1 = data[2]
+ video2 = data[3]
} else {
- video1 = videos[3]
- video2 = videos[2]
+ video1 = data[3]
+ video2 = data[2]
}
const checkAttributesVideo1 = {
}
]
}
- await completeVideoCheck(server.url, video1, checkAttributesVideo1)
+ await completeVideoCheck(server, video1, checkAttributesVideo1)
const checkAttributesVideo2 = {
name: 'my super name for server 3-2',
}
]
}
- await completeVideoCheck(server.url, video2, checkAttributesVideo2)
+ await completeVideoCheck(server, video2, checkAttributesVideo2)
}
})
})
describe('It should list local videos', function () {
it('Should list only local videos on server 1', async function () {
- const { body } = await getLocalVideos(servers[0].url)
+ const { data, total } = await servers[0].videos.list({ filter: 'local' })
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
- expect(body.data[0].name).to.equal('my super name for server 1')
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(1)
+ expect(data[0].name).to.equal('my super name for server 1')
})
it('Should list only local videos on server 2', async function () {
- const { body } = await getLocalVideos(servers[1].url)
+ const { data, total } = await servers[1].videos.list({ filter: 'local' })
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
- expect(body.data[0].name).to.equal('my super name for server 2')
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(1)
+ expect(data[0].name).to.equal('my super name for server 2')
})
it('Should list only local videos on server 3', async function () {
- const { body } = await getLocalVideos(servers[2].url)
+ const { data, total } = await servers[2].videos.list({ filter: 'local' })
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(2)
- expect(body.data[0].name).to.equal('my super name for server 3')
- expect(body.data[1].name).to.equal('my super name for server 3-2')
+ expect(total).to.equal(2)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(2)
+ expect(data[0].name).to.equal('my super name for server 3')
+ expect(data[1].name).to.equal('my super name for server 3-2')
})
})
it('Should add the file 1 by asking server 3', async function () {
this.timeout(10000)
- const res = await getVideosList(servers[2].url)
-
- const video = res.body.data[0]
- toRemove.push(res.body.data[2])
- toRemove.push(res.body.data[3])
+ const { data } = await servers[2].videos.list()
- const res2 = await getVideo(servers[2].url, video.id)
- const videoDetails = res2.body
+ const video = data[0]
+ toRemove.push(data[2])
+ toRemove.push(data[3])
+ const videoDetails = await servers[2].videos.get({ id: video.id })
const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri, true)
expect(torrent.files).to.be.an('array')
expect(torrent.files.length).to.equal(1)
it('Should add the file 2 by asking server 1', async function () {
this.timeout(10000)
- const res = await getVideosList(servers[0].url)
+ const { data } = await servers[0].videos.list()
- const video = res.body.data[1]
- const res2 = await getVideo(servers[0].url, video.id)
- const videoDetails = res2.body
+ const video = data[1]
+ const videoDetails = await servers[0].videos.get({ id: video.id })
const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri, true)
expect(torrent.files).to.be.an('array')
it('Should add the file 3 by asking server 2', async function () {
this.timeout(10000)
- const res = await getVideosList(servers[1].url)
+ const { data } = await servers[1].videos.list()
- const video = res.body.data[2]
- const res2 = await getVideo(servers[1].url, video.id)
- const videoDetails = res2.body
+ const video = data[2]
+ const videoDetails = await servers[1].videos.get({ id: video.id })
const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri, true)
expect(torrent.files).to.be.an('array')
it('Should add the file 3-2 by asking server 1', async function () {
this.timeout(10000)
- const res = await getVideosList(servers[0].url)
+ const { data } = await servers[0].videos.list()
- const video = res.body.data[3]
- const res2 = await getVideo(servers[0].url, video.id)
- const videoDetails = res2.body
+ const video = data[3]
+ const videoDetails = await servers[0].videos.get({ id: video.id })
const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri)
expect(torrent.files).to.be.an('array')
it('Should add the file 2 in 360p by asking server 1', async function () {
this.timeout(10000)
- const res = await getVideosList(servers[0].url)
+ const { data } = await servers[0].videos.list()
- const video = res.body.data.find(v => v.name === 'my super name for server 2')
- const res2 = await getVideo(servers[0].url, video.id)
- const videoDetails = res2.body
+ const video = data.find(v => v.name === 'my super name for server 2')
+ const videoDetails = await servers[0].videos.get({ id: video.id })
const file = videoDetails.files.find(f => f.resolution.id === 360)
expect(file).not.to.be.undefined
let remoteVideosServer3 = []
before(async function () {
- const res1 = await getVideosList(servers[0].url)
- remoteVideosServer1 = res1.body.data.filter(video => video.isLocal === false).map(video => video.uuid)
+ {
+ const { data } = await servers[0].videos.list()
+ remoteVideosServer1 = data.filter(video => video.isLocal === false).map(video => video.uuid)
+ }
- const res2 = await getVideosList(servers[1].url)
- remoteVideosServer2 = res2.body.data.filter(video => video.isLocal === false).map(video => video.uuid)
+ {
+ const { data } = await servers[1].videos.list()
+ remoteVideosServer2 = data.filter(video => video.isLocal === false).map(video => video.uuid)
+ }
- const res3 = await getVideosList(servers[2].url)
- localVideosServer3 = res3.body.data.filter(video => video.isLocal === true).map(video => video.uuid)
- remoteVideosServer3 = res3.body.data.filter(video => video.isLocal === false).map(video => video.uuid)
+ {
+ const { data } = await servers[2].videos.list()
+ localVideosServer3 = data.filter(video => video.isLocal === true).map(video => video.uuid)
+ remoteVideosServer3 = data.filter(video => video.isLocal === false).map(video => video.uuid)
+ }
})
it('Should view multiple videos on owned servers', async function () {
this.timeout(30000)
- await viewVideo(servers[2].url, localVideosServer3[0])
+ await servers[2].videos.view({ id: localVideosServer3[0] })
await wait(1000)
- await viewVideo(servers[2].url, localVideosServer3[0])
- await viewVideo(servers[2].url, localVideosServer3[1])
+ await servers[2].videos.view({ id: localVideosServer3[0] })
+ await servers[2].videos.view({ id: localVideosServer3[1] })
await wait(1000)
- await viewVideo(servers[2].url, localVideosServer3[0])
- await viewVideo(servers[2].url, localVideosServer3[0])
+ await servers[2].videos.view({ id: localVideosServer3[0] })
+ await servers[2].videos.view({ id: localVideosServer3[0] })
await waitJobs(servers)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const videos = res.body.data
- const video0 = videos.find(v => v.uuid === localVideosServer3[0])
- const video1 = videos.find(v => v.uuid === localVideosServer3[1])
+ const video0 = data.find(v => v.uuid === localVideosServer3[0])
+ const video1 = data.find(v => v.uuid === localVideosServer3[1])
expect(video0.views).to.equal(3)
expect(video1.views).to.equal(1)
this.timeout(45000)
const tasks: Promise<any>[] = []
- tasks.push(viewVideo(servers[0].url, remoteVideosServer1[0]))
- tasks.push(viewVideo(servers[1].url, remoteVideosServer2[0]))
- tasks.push(viewVideo(servers[1].url, remoteVideosServer2[0]))
- tasks.push(viewVideo(servers[2].url, remoteVideosServer3[0]))
- tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1]))
- tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1]))
- tasks.push(viewVideo(servers[2].url, remoteVideosServer3[1]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[1]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[1]))
- tasks.push(viewVideo(servers[2].url, localVideosServer3[1]))
+ tasks.push(servers[0].videos.view({ id: remoteVideosServer1[0] }))
+ tasks.push(servers[1].videos.view({ id: remoteVideosServer2[0] }))
+ tasks.push(servers[1].videos.view({ id: remoteVideosServer2[0] }))
+ tasks.push(servers[2].videos.view({ id: remoteVideosServer3[0] }))
+ tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
+ tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
+ tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
+ tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
+ tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
+ tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
await Promise.all(tasks)
let baseVideos = null
for (const server of servers) {
- const res = await getVideosList(server.url)
-
- const videos = res.body.data
+ const { data } = await server.videos.list()
// Initialize base videos for future comparisons
if (baseVideos === null) {
- baseVideos = videos
+ baseVideos = data
continue
}
for (const baseVideo of baseVideos) {
- const sameVideo = videos.find(video => video.name === baseVideo.name)
+ const sameVideo = data.find(video => video.name === baseVideo.name)
expect(baseVideo.views).to.equal(sameVideo.views)
}
}
it('Should like and dislikes videos on different services', async function () {
this.timeout(50000)
- await rateVideo(servers[0].url, servers[0].accessToken, remoteVideosServer1[0], 'like')
+ await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
await wait(500)
- await rateVideo(servers[0].url, servers[0].accessToken, remoteVideosServer1[0], 'dislike')
+ await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'dislike' })
await wait(500)
- await rateVideo(servers[0].url, servers[0].accessToken, remoteVideosServer1[0], 'like')
- await rateVideo(servers[2].url, servers[2].accessToken, localVideosServer3[1], 'like')
+ await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
+ await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'like' })
await wait(500)
- await rateVideo(servers[2].url, servers[2].accessToken, localVideosServer3[1], 'dislike')
- await rateVideo(servers[2].url, servers[2].accessToken, remoteVideosServer3[1], 'dislike')
+ await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'dislike' })
+ await servers[2].videos.rate({ id: remoteVideosServer3[1], rating: 'dislike' })
await wait(500)
- await rateVideo(servers[2].url, servers[2].accessToken, remoteVideosServer3[0], 'like')
+ await servers[2].videos.rate({ id: remoteVideosServer3[0], rating: 'like' })
await waitJobs(servers)
await wait(5000)
+ await waitJobs(servers)
let baseVideos = null
for (const server of servers) {
- const res = await getVideosList(server.url)
-
- const videos = res.body.data
+ const { data } = await server.videos.list()
// Initialize base videos for future comparisons
if (baseVideos === null) {
- baseVideos = videos
+ baseVideos = data
continue
}
for (const baseVideo of baseVideos) {
- const sameVideo = videos.find(video => video.name === baseVideo.name)
+ const sameVideo = data.find(video => video.name === baseVideo.name)
expect(baseVideo.likes).to.equal(sameVideo.likes)
expect(baseVideo.dislikes).to.equal(sameVideo.dislikes)
}
previewfile: 'preview.jpg'
}
- await updateVideo(servers[2].url, servers[2].accessToken, toRemove[0].id, attributes)
+ await servers[2].videos.update({ id: toRemove[0].id, attributes })
await waitJobs(servers)
})
this.timeout(10000)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const videos = res.body.data
- const videoUpdated = videos.find(video => video.name === 'my super video updated')
+ const videoUpdated = data.find(video => video.name === 'my super video updated')
expect(!!videoUpdated).to.be.true
const isLocal = server.url === 'http://localhost:' + servers[2].port
thumbnailfile: 'thumbnail',
previewfile: 'preview'
}
- await completeVideoCheck(server.url, videoUpdated, checkAttributes)
+ await completeVideoCheck(server, videoUpdated, checkAttributes)
}
})
- it('Should remove the videos 3 and 3-2 by asking server 3', async function () {
- this.timeout(10000)
+ it('Should remove the videos 3 and 3-2 by asking server 3 and correctly delete files', async function () {
+ this.timeout(30000)
- await removeVideo(servers[2].url, servers[2].accessToken, toRemove[0].id)
- await removeVideo(servers[2].url, servers[2].accessToken, toRemove[1].id)
+ for (const id of [ toRemove[0].id, toRemove[1].id ]) {
+ await saveVideoInServers(servers, id)
- await waitJobs(servers)
- })
+ await servers[2].videos.remove({ id })
- it('Should not have files of videos 3 and 3-2 on each server', async function () {
- for (const server of servers) {
- await checkVideoFilesWereRemoved(toRemove[0].uuid, server.internalServerNumber)
- await checkVideoFilesWereRemoved(toRemove[1].uuid, server.internalServerNumber)
+ await waitJobs(servers)
+
+ for (const server of servers) {
+ await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
+ }
}
})
it('Should have videos 1 and 3 on each server', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
-
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(2)
- expect(videos[0].name).not.to.equal(videos[1].name)
- expect(videos[0].name).not.to.equal(toRemove[0].name)
- expect(videos[1].name).not.to.equal(toRemove[0].name)
- expect(videos[0].name).not.to.equal(toRemove[1].name)
- expect(videos[1].name).not.to.equal(toRemove[1].name)
-
- videoUUID = videos.find(video => video.name === 'my super name for server 1').uuid
+ const { data } = await server.videos.list()
+
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(2)
+ expect(data[0].name).not.to.equal(data[1].name)
+ expect(data[0].name).not.to.equal(toRemove[0].name)
+ expect(data[1].name).not.to.equal(toRemove[0].name)
+ expect(data[0].name).not.to.equal(toRemove[1].name)
+ expect(data[1].name).not.to.equal(toRemove[1].name)
+
+ videoUUID = data.find(video => video.name === 'my super name for server 1').uuid
}
})
it('Should get the same video by UUID on each server', async function () {
let baseVideo = null
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
-
- const video = res.body
+ const video = await server.videos.get({ id: videoUUID })
if (baseVideo === null) {
baseVideo = video
it('Should get the preview from each server', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video = res.body
+ const video = await server.videos.get({ id: videoUUID })
await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
}
{
const text = 'my super first comment'
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, text)
+ await servers[0].comments.createThread({ videoId: videoUUID, text })
}
{
const text = 'my super second comment'
- await addVideoCommentThread(servers[2].url, servers[2].accessToken, videoUUID, text)
+ await servers[2].comments.createThread({ videoId: videoUUID, text })
}
await waitJobs(servers)
{
- const threadId = await findCommentId(servers[1].url, videoUUID, 'my super first comment')
+ const threadId = await servers[1].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
const text = 'my super answer to thread 1'
- await addVideoCommentReply(servers[1].url, servers[1].accessToken, videoUUID, threadId, text)
+ await servers[1].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text })
}
await waitJobs(servers)
{
- const threadId = await findCommentId(servers[2].url, videoUUID, 'my super first comment')
+ const threadId = await servers[2].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
- const res2 = await getVideoThreadComments(servers[2].url, videoUUID, threadId)
- const childCommentId = res2.body.children[0].comment.id
+ const body = await servers[2].comments.getThread({ videoId: videoUUID, threadId })
+ const childCommentId = body.children[0].comment.id
const text3 = 'my second answer to thread 1'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, videoUUID, threadId, text3)
+ await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: text3 })
const text2 = 'my super answer to answer of thread 1'
- await addVideoCommentReply(servers[2].url, servers[2].accessToken, videoUUID, childCommentId, text2)
+ await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: childCommentId, text: text2 })
}
await waitJobs(servers)
it('Should have these threads', async function () {
for (const server of servers) {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
+ const body = await server.comments.listThreads({ videoId: videoUUID })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(2)
{
- const comment: VideoComment = res.body.data.find(c => c.text === 'my super first comment')
+ const comment = body.data.find(c => c.text === 'my super first comment')
expect(comment).to.not.be.undefined
expect(comment.inReplyToCommentId).to.be.null
expect(comment.account.name).to.equal('root')
}
{
- const comment: VideoComment = res.body.data.find(c => c.text === 'my super second comment')
+ const comment = body.data.find(c => c.text === 'my super second comment')
expect(comment).to.not.be.undefined
expect(comment.inReplyToCommentId).to.be.null
expect(comment.account.name).to.equal('root')
it('Should have these comments', async function () {
for (const server of servers) {
- const res1 = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
- const threadId = res1.body.data.find(c => c.text === 'my super first comment').id
+ const body = await server.comments.listThreads({ videoId: videoUUID })
+ const threadId = body.data.find(c => c.text === 'my super first comment').id
- const res2 = await getVideoThreadComments(server.url, videoUUID, threadId)
+ const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
- const tree: VideoCommentThreadTree = res2.body
expect(tree.comment.text).equal('my super first comment')
expect(tree.comment.account.name).equal('root')
expect(tree.comment.account.host).equal('localhost:' + servers[0].port)
it('Should delete a reply', async function () {
this.timeout(10000)
- await deleteVideoComment(servers[2].url, servers[2].accessToken, videoUUID, childOfFirstChild.comment.id)
+ await servers[2].comments.delete({ videoId: videoUUID, commentId: childOfFirstChild.comment.id })
await waitJobs(servers)
})
it('Should have this comment marked as deleted', async function () {
for (const server of servers) {
- const res1 = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
- const threadId = res1.body.data.find(c => c.text === 'my super first comment').id
-
- const res2 = await getVideoThreadComments(server.url, videoUUID, threadId)
+ const { data } = await server.comments.listThreads({ videoId: videoUUID })
+ const threadId = data.find(c => c.text === 'my super first comment').id
- const tree: VideoCommentThreadTree = res2.body
+ const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
expect(tree.comment.text).equal('my super first comment')
const firstChild = tree.children[0]
it('Should delete the thread comments', async function () {
this.timeout(10000)
- const res = await getVideoCommentThreads(servers[0].url, videoUUID, 0, 5)
- const threadId = res.body.data.find(c => c.text === 'my super first comment').id
- await deleteVideoComment(servers[0].url, servers[0].accessToken, videoUUID, threadId)
+ const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
+ const commentId = data.find(c => c.text === 'my super first comment').id
+ await servers[0].comments.delete({ videoId: videoUUID, commentId })
await waitJobs(servers)
})
it('Should have the threads marked as deleted on other servers too', async function () {
for (const server of servers) {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
+ const body = await server.comments.listThreads({ videoId: videoUUID })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(2)
{
- const comment: VideoComment = res.body.data[0]
+ const comment = body.data[0]
expect(comment).to.not.be.undefined
expect(comment.inReplyToCommentId).to.be.null
expect(comment.account.name).to.equal('root')
}
{
- const deletedComment: VideoComment = res.body.data[1]
+ const deletedComment = body.data[1]
expect(deletedComment).to.not.be.undefined
expect(deletedComment.isDeleted).to.be.true
expect(deletedComment.deletedAt).to.not.be.null
it('Should delete a remote thread by the origin server', async function () {
this.timeout(5000)
- const res = await getVideoCommentThreads(servers[0].url, videoUUID, 0, 5)
- const threadId = res.body.data.find(c => c.text === 'my super second comment').id
- await deleteVideoComment(servers[0].url, servers[0].accessToken, videoUUID, threadId)
+ const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
+ const commentId = data.find(c => c.text === 'my super second comment').id
+ await servers[0].comments.delete({ videoId: videoUUID, commentId })
await waitJobs(servers)
})
it('Should have the threads marked as deleted on other servers too', async function () {
for (const server of servers) {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
+ const body = await server.comments.listThreads({ videoId: videoUUID })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
{
- const comment: VideoComment = res.body.data[0]
+ const comment = body.data[0]
expect(comment.text).to.equal('')
expect(comment.isDeleted).to.be.true
expect(comment.createdAt).to.not.be.null
}
{
- const comment: VideoComment = res.body.data[1]
+ const comment = body.data[1]
expect(comment.text).to.equal('')
expect(comment.isDeleted).to.be.true
expect(comment.createdAt).to.not.be.null
downloadEnabled: false
}
- await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, attributes)
+ await servers[0].videos.update({ id: videoUUID, attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- expect(res.body.commentsEnabled).to.be.false
- expect(res.body.downloadEnabled).to.be.false
+ const video = await server.videos.get({ id: videoUUID })
+ expect(video.commentsEnabled).to.be.false
+ expect(video.downloadEnabled).to.be.false
const text = 'my super forbidden comment'
- await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, HttpStatusCode.CONFLICT_409)
+ await server.comments.createThread({ videoId: videoUUID, text, expectedStatus: HttpStatusCode.CONFLICT_409 })
}
})
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const video = res.body.data.find(v => v.name === 'minimum parameters')
+ const { data } = await server.videos.list()
+ const video = data.find(v => v.name === 'minimum parameters')
const isLocal = server.url === 'http://localhost:' + servers[1].port
const checkAttributes = {
}
]
}
- await completeVideoCheck(server.url, video, checkAttributes)
+ await completeVideoCheck(server, video, checkAttributes)
}
})
})
import * as chai from 'chai'
import { pathExists, readdir, stat } from 'fs-extra'
import { join } from 'path'
-import { HttpStatusCode } from '@shared/core-utils'
import {
buildAbsoluteFixturePath,
- buildServerDirectory,
cleanupTests,
- flushAndRunServer,
- getMyUserInformation,
- prepareResumableUpload,
- sendDebugCommand,
- sendResumableChunks,
- ServerInfo,
+ createSingleServer,
+ PeerTubeServer,
setAccessTokensToServers,
- setDefaultVideoChannel,
- updateUser
+ setDefaultVideoChannel
} from '@shared/extra-utils'
-import { MyUser, VideoPrivacy } from '@shared/models'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test resumable upload', function () {
const defaultFixture = 'video_short.mp4'
- let server: ServerInfo
+ let server: PeerTubeServer
let rootId: number
async function buildSize (fixture: string, size?: number) {
const attributes = {
name: 'video',
- channelId: server.videoChannel.id,
+ channelId: server.store.channel.id,
privacy: VideoPrivacy.PUBLIC,
fixture: defaultFixture
}
const mimetype = 'video/mp4'
- const res = await prepareResumableUpload({ url: server.url, token: server.accessToken, attributes, size, mimetype })
+ const res = await server.videos.prepareResumableUpload({ attributes, size, mimetype })
return res.header['location'].split('?')[1]
}
const size = await buildSize(defaultFixture, options.size)
const absoluteFilePath = buildAbsoluteFixturePath(defaultFixture)
- return sendResumableChunks({
- url: server.url,
- token: server.accessToken,
+ return server.videos.sendResumableChunks({
pathUploadId,
videoFilePath: absoluteFilePath,
size,
contentLength,
contentRangeBuilder,
- specialStatus: expectedStatus
+ expectedStatus
})
}
const uploadId = uploadIdArg.replace(/^upload_id=/, '')
const subPath = join('tmp', 'resumable-uploads', uploadId)
- const filePath = buildServerDirectory(server, subPath)
+ const filePath = server.servers.buildDirectory(subPath)
const exists = await pathExists(filePath)
if (expectedSize === null) {
async function countResumableUploads () {
const subPath = join('tmp', 'resumable-uploads')
- const filePath = buildServerDirectory(server, subPath)
+ const filePath = server.servers.buildDirectory(subPath)
const files = await readdir(filePath)
return files.length
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
- const res = await getMyUserInformation(server.url, server.accessToken)
- rootId = (res.body as MyUser).id
+ const body = await server.users.getMyInfo()
+ rootId = body.id
- await updateUser({
- url: server.url,
- userId: rootId,
- accessToken: server.accessToken,
- videoQuota: 10_000_000
- })
+ await server.users.update({ userId: rootId, videoQuota: 10_000_000 })
})
describe('Directory cleaning', function () {
})
it('Should not delete recent uploads', async function () {
- await sendDebugCommand(server.url, server.accessToken, { command: 'remove-dandling-resumable-uploads' })
+ await server.debug.sendCommand({ body: { command: 'remove-dandling-resumable-uploads' } })
expect(await countResumableUploads()).to.equal(2)
})
it('Should delete old uploads', async function () {
- await sendDebugCommand(server.url, server.accessToken, { command: 'remove-dandling-resumable-uploads' })
+ await server.debug.sendCommand({ body: { command: 'remove-dandling-resumable-uploads' } })
expect(await countResumableUploads()).to.equal(0)
})
})
it('Should not accept more chunks than expected', async function () {
- const size = 100
- const uploadId = await prepareUpload(size)
+ const uploadId = await prepareUpload(100)
await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409 })
await checkFileSize(uploadId, 0)
it('Should not accept more chunks than expected with an invalid content length/content range', async function () {
const uploadId = await prepareUpload(1500)
- await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.BAD_REQUEST_400, contentLength: 1000 })
- await checkFileSize(uploadId, 0)
+ // Content length check seems to have changed in v16
+ if (process.version.startsWith('v16')) {
+ await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409, contentLength: 1000 })
+ await checkFileSize(uploadId, 1000)
+ } else {
+ await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.BAD_REQUEST_400, contentLength: 1000 })
+ await checkFileSize(uploadId, 0)
+ }
})
it('Should not accept more chunks than expected with an invalid content length', async function () {
const size = 1000
- const contentRangeBuilder = start => `bytes ${start}-${start + size - 1}/${size}`
- await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.BAD_REQUEST_400, contentRangeBuilder, contentLength: size })
+ // Content length check seems to have changed in v16
+ const expectedStatus = process.version.startsWith('v16')
+ ? HttpStatusCode.CONFLICT_409
+ : HttpStatusCode.BAD_REQUEST_400
+
+ const contentRangeBuilder = (start: number) => `bytes ${start}-${start + size - 1}/${size}`
+ await sendChunks({ pathUploadId: uploadId, expectedStatus, contentRangeBuilder, contentLength: size })
await checkFileSize(uploadId, 0)
})
})
import 'mocha'
import * as chai from 'chai'
-import { keyBy } from 'lodash'
-
import {
checkVideoFilesWereRemoved,
cleanupTests,
completeVideoCheck,
- flushAndRunServer,
- getVideo,
- getVideoCategories,
- getVideoLanguages,
- getVideoLicences,
- getVideoPrivacies,
- getVideosList,
- getVideosListPagination,
- getVideosListSort,
- getVideosWithFilters,
- rateVideo,
- removeVideo,
- ServerInfo,
+ createSingleServer,
+ PeerTubeServer,
setAccessTokensToServers,
testImage,
- updateVideo,
- uploadVideo,
- viewVideo,
wait
-} from '../../../../shared/extra-utils'
-import { VideoPrivacy } from '../../../../shared/models/videos'
-import { HttpStatusCode } from '@shared/core-utils'
+} from '@shared/extra-utils'
+import { Video, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test a single server', function () {
function runSuite (mode: 'legacy' | 'resumable') {
- let server: ServerInfo = null
- let videoId = -1
- let videoId2 = -1
+ let server: PeerTubeServer = null
+ let videoId: number | string
+ let videoId2: string
let videoUUID = ''
let videosListBase: any[] = null
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
it('Should list video categories', async function () {
- const res = await getVideoCategories(server.url)
-
- const categories = res.body
+ const categories = await server.videos.getCategories()
expect(Object.keys(categories)).to.have.length.above(10)
expect(categories[11]).to.equal('News & Politics')
})
it('Should list video licences', async function () {
- const res = await getVideoLicences(server.url)
-
- const licences = res.body
+ const licences = await server.videos.getLicences()
expect(Object.keys(licences)).to.have.length.above(5)
expect(licences[3]).to.equal('Attribution - No Derivatives')
})
it('Should list video languages', async function () {
- const res = await getVideoLanguages(server.url)
-
- const languages = res.body
+ const languages = await server.videos.getLanguages()
expect(Object.keys(languages)).to.have.length.above(5)
expect(languages['ru']).to.equal('Russian')
})
it('Should list video privacies', async function () {
- const res = await getVideoPrivacies(server.url)
-
- const privacies = res.body
+ const privacies = await server.videos.getPrivacies()
expect(Object.keys(privacies)).to.have.length.at.least(3)
expect(privacies[3]).to.equal('Private')
})
it('Should not have videos', async function () {
- const res = await getVideosList(server.url)
+ const { data, total } = await server.videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(total).to.equal(0)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(0)
})
it('Should upload the video', async function () {
this.timeout(10000)
- const videoAttributes = {
+ const attributes = {
name: 'my super name',
category: 2,
nsfw: true,
licence: 6,
tags: [ 'tag1', 'tag2', 'tag3' ]
}
- const res = await uploadVideo(server.url, server.accessToken, videoAttributes, HttpStatusCode.OK_200, mode)
- expect(res.body.video).to.not.be.undefined
- expect(res.body.video.id).to.equal(1)
- expect(res.body.video.uuid).to.have.length.above(5)
+ const video = await server.videos.upload({ attributes, mode })
+ expect(video).to.not.be.undefined
+ expect(video.id).to.equal(1)
+ expect(video.uuid).to.have.length.above(5)
- videoId = res.body.video.id
- videoUUID = res.body.video.uuid
+ videoId = video.id
+ videoUUID = video.uuid
})
it('Should get and seed the uploaded video', async function () {
this.timeout(5000)
- const res = await getVideosList(server.url)
+ const { data, total } = await server.videos.list()
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(1)
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data.length).to.equal(1)
- const video = res.body.data[0]
- await completeVideoCheck(server.url, video, getCheckAttributes())
+ const video = data[0]
+ await completeVideoCheck(server, video, getCheckAttributes())
})
it('Should get the video by UUID', async function () {
this.timeout(5000)
- const res = await getVideo(server.url, videoUUID)
-
- const video = res.body
- await completeVideoCheck(server.url, video, getCheckAttributes())
+ const video = await server.videos.get({ id: videoUUID })
+ await completeVideoCheck(server, video, getCheckAttributes())
})
it('Should have the views updated', async function () {
this.timeout(20000)
- await viewVideo(server.url, videoId)
- await viewVideo(server.url, videoId)
- await viewVideo(server.url, videoId)
+ await server.videos.view({ id: videoId })
+ await server.videos.view({ id: videoId })
+ await server.videos.view({ id: videoId })
await wait(1500)
- await viewVideo(server.url, videoId)
- await viewVideo(server.url, videoId)
+ await server.videos.view({ id: videoId })
+ await server.videos.view({ id: videoId })
await wait(1500)
- await viewVideo(server.url, videoId)
- await viewVideo(server.url, videoId)
+ await server.videos.view({ id: videoId })
+ await server.videos.view({ id: videoId })
// Wait the repeatable job
await wait(8000)
- const res = await getVideo(server.url, videoId)
-
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
expect(video.views).to.equal(3)
})
it('Should remove the video', async function () {
- await removeVideo(server.url, server.accessToken, videoId)
+ const video = await server.videos.get({ id: videoId })
+ await server.videos.remove({ id: videoId })
- await checkVideoFilesWereRemoved(videoUUID, 1)
+ await checkVideoFilesWereRemoved({ video, server })
})
it('Should not have videos', async function () {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(0)
})
it('Should upload 6 videos', async function () {
])
for (const video of videos) {
- const videoAttributes = {
+ const attributes = {
name: video + ' name',
description: video + ' description',
category: 2,
fixture: video
}
- await uploadVideo(server.url, server.accessToken, videoAttributes, HttpStatusCode.OK_200, mode)
+ await server.videos.upload({ attributes, mode })
}
})
it('Should have the correct durations', async function () {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
+
+ expect(total).to.equal(6)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(6)
- expect(res.body.total).to.equal(6)
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(6)
+ const videosByName: { [ name: string ]: Video } = {}
+ data.forEach(v => { videosByName[v.name] = v })
- const videosByName = keyBy<{ duration: number }>(videos, 'name')
expect(videosByName['video_short.mp4 name'].duration).to.equal(5)
expect(videosByName['video_short.ogv name'].duration).to.equal(5)
expect(videosByName['video_short.webm name'].duration).to.equal(5)
})
it('Should have the correct thumbnails', async function () {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const videos = res.body.data
// For the next test
- videosListBase = videos
+ videosListBase = data
- for (const video of videos) {
+ for (const video of data) {
const videoName = video.name.replace(' name', '')
await testImage(server.url, videoName, video.thumbnailPath)
}
})
it('Should list only the two first videos', async function () {
- const res = await getVideosListPagination(server.url, 0, 2, 'name')
+ const { total, data } = await server.videos.list({ start: 0, count: 2, sort: 'name' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(2)
- expect(videos[0].name).to.equal(videosListBase[0].name)
- expect(videos[1].name).to.equal(videosListBase[1].name)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(2)
+ expect(data[0].name).to.equal(videosListBase[0].name)
+ expect(data[1].name).to.equal(videosListBase[1].name)
})
it('Should list only the next three videos', async function () {
- const res = await getVideosListPagination(server.url, 2, 3, 'name')
+ const { total, data } = await server.videos.list({ start: 2, count: 3, sort: 'name' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(3)
- expect(videos[0].name).to.equal(videosListBase[2].name)
- expect(videos[1].name).to.equal(videosListBase[3].name)
- expect(videos[2].name).to.equal(videosListBase[4].name)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(3)
+ expect(data[0].name).to.equal(videosListBase[2].name)
+ expect(data[1].name).to.equal(videosListBase[3].name)
+ expect(data[2].name).to.equal(videosListBase[4].name)
})
it('Should list the last video', async function () {
- const res = await getVideosListPagination(server.url, 5, 6, 'name')
+ const { total, data } = await server.videos.list({ start: 5, count: 6, sort: 'name' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(1)
- expect(videos[0].name).to.equal(videosListBase[5].name)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(1)
+ expect(data[0].name).to.equal(videosListBase[5].name)
})
it('Should not have the total field', async function () {
- const res = await getVideosListPagination(server.url, 5, 6, 'name', true)
+ const { total, data } = await server.videos.list({ start: 5, count: 6, sort: 'name', skipCount: true })
- const videos = res.body.data
- expect(res.body.total).to.not.exist
- expect(videos.length).to.equal(1)
- expect(videos[0].name).to.equal(videosListBase[5].name)
+ expect(total).to.not.exist
+ expect(data.length).to.equal(1)
+ expect(data[0].name).to.equal(videosListBase[5].name)
})
it('Should list and sort by name in descending order', async function () {
- const res = await getVideosListSort(server.url, '-name')
+ const { total, data } = await server.videos.list({ sort: '-name' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(6)
- expect(videos[0].name).to.equal('video_short.webm name')
- expect(videos[1].name).to.equal('video_short.ogv name')
- expect(videos[2].name).to.equal('video_short.mp4 name')
- expect(videos[3].name).to.equal('video_short3.webm name')
- expect(videos[4].name).to.equal('video_short2.webm name')
- expect(videos[5].name).to.equal('video_short1.webm name')
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(6)
+ expect(data[0].name).to.equal('video_short.webm name')
+ expect(data[1].name).to.equal('video_short.ogv name')
+ expect(data[2].name).to.equal('video_short.mp4 name')
+ expect(data[3].name).to.equal('video_short3.webm name')
+ expect(data[4].name).to.equal('video_short2.webm name')
+ expect(data[5].name).to.equal('video_short1.webm name')
- videoId = videos[3].uuid
- videoId2 = videos[5].uuid
+ videoId = data[3].uuid
+ videoId2 = data[5].uuid
})
it('Should list and sort by trending in descending order', async function () {
- const res = await getVideosListPagination(server.url, 0, 2, '-trending')
+ const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-trending' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(2)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(2)
})
it('Should list and sort by hotness in descending order', async function () {
- const res = await getVideosListPagination(server.url, 0, 2, '-hot')
+ const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-hot' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(2)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(2)
})
it('Should list and sort by best in descending order', async function () {
- const res = await getVideosListPagination(server.url, 0, 2, '-best')
+ const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-best' })
- const videos = res.body.data
- expect(res.body.total).to.equal(6)
- expect(videos.length).to.equal(2)
+ expect(total).to.equal(6)
+ expect(data.length).to.equal(2)
})
it('Should update a video', async function () {
downloadEnabled: false,
tags: [ 'tagup1', 'tagup2' ]
}
- await updateVideo(server.url, server.accessToken, videoId, attributes)
+ await server.videos.update({ id: videoId, attributes })
})
it('Should filter by tags and category', async function () {
- const res1 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 4 ] })
- expect(res1.body.total).to.equal(1)
- expect(res1.body.data[0].name).to.equal('my super video updated')
+ {
+ const { data, total } = await server.videos.list({ tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 4 ] })
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('my super video updated')
+ }
- const res2 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 3 ] })
- expect(res2.body.total).to.equal(0)
+ {
+ const { total } = await server.videos.list({ tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 3 ] })
+ expect(total).to.equal(0)
+ }
})
it('Should have the video updated', async function () {
this.timeout(60000)
- const res = await getVideo(server.url, videoId)
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
- await completeVideoCheck(server.url, video, updateCheckAttributes())
+ await completeVideoCheck(server, video, updateCheckAttributes())
})
it('Should update only the tags of a video', async function () {
const attributes = {
tags: [ 'supertag', 'tag1', 'tag2' ]
}
- await updateVideo(server.url, server.accessToken, videoId, attributes)
+ await server.videos.update({ id: videoId, attributes })
- const res = await getVideo(server.url, videoId)
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
- await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes(), attributes))
+ await completeVideoCheck(server, video, Object.assign(updateCheckAttributes(), attributes))
})
it('Should update only the description of a video', async function () {
const attributes = {
description: 'hello everybody'
}
- await updateVideo(server.url, server.accessToken, videoId, attributes)
+ await server.videos.update({ id: videoId, attributes })
- const res = await getVideo(server.url, videoId)
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
const expectedAttributes = Object.assign(updateCheckAttributes(), { tags: [ 'supertag', 'tag1', 'tag2' ] }, attributes)
- await completeVideoCheck(server.url, video, expectedAttributes)
+ await completeVideoCheck(server, video, expectedAttributes)
})
it('Should like a video', async function () {
- await rateVideo(server.url, server.accessToken, videoId, 'like')
+ await server.videos.rate({ id: videoId, rating: 'like' })
- const res = await getVideo(server.url, videoId)
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
expect(video.likes).to.equal(1)
expect(video.dislikes).to.equal(0)
})
it('Should dislike the same video', async function () {
- await rateVideo(server.url, server.accessToken, videoId, 'dislike')
+ await server.videos.rate({ id: videoId, rating: 'dislike' })
- const res = await getVideo(server.url, videoId)
- const video = res.body
+ const video = await server.videos.get({ id: videoId })
expect(video.likes).to.equal(0)
expect(video.dislikes).to.equal(1)
{
const now = new Date()
const attributes = { originallyPublishedAt: now.toISOString() }
- await updateVideo(server.url, server.accessToken, videoId, attributes)
+ await server.videos.update({ id: videoId, attributes })
- const res = await getVideosListSort(server.url, '-originallyPublishedAt')
- const names = res.body.data.map(v => v.name)
+ const { data } = await server.videos.list({ sort: '-originallyPublishedAt' })
+ const names = data.map(v => v.name)
expect(names[0]).to.equal('my super video updated')
expect(names[1]).to.equal('video_short2.webm name')
{
const now = new Date()
const attributes = { originallyPublishedAt: now.toISOString() }
- await updateVideo(server.url, server.accessToken, videoId2, attributes)
+ await server.videos.update({ id: videoId2, attributes })
- const res = await getVideosListSort(server.url, '-originallyPublishedAt')
- const names = res.body.data.map(v => v.name)
+ const { data } = await server.videos.list({ sort: '-originallyPublishedAt' })
+ const names = data.map(v => v.name)
expect(names[0]).to.equal('video_short1.webm name')
expect(names[1]).to.equal('my super video updated')
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
checkVideoFilesWereRemoved,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- removeVideo,
- uploadVideo,
- wait
-} from '../../../../shared/extra-utils'
-import { ServerInfo, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- createVideoCaption,
- deleteVideoCaption,
- listVideoCaptions,
- testCaptionFile
-} from '../../../../shared/extra-utils/videos/video-captions'
-import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model'
+ PeerTubeServer,
+ setAccessTokensToServers,
+ testCaptionFile,
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test video captions', function () {
const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoUUID: string
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
await waitJobs(servers)
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'my video name' })
- videoUUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video name' } })
+ videoUUID = uuid
await waitJobs(servers)
})
it('Should list the captions and return an empty list', async function () {
for (const server of servers) {
- const res = await listVideoCaptions(server.url, videoUUID)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await server.captions.list({ videoId: videoUUID })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
})
it('Should create two new captions', async function () {
this.timeout(30000)
- await createVideoCaption({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].captions.add({
language: 'ar',
videoId: videoUUID,
fixture: 'subtitle-good1.vtt'
})
- await createVideoCaption({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].captions.add({
language: 'zh',
videoId: videoUUID,
fixture: 'subtitle-good2.vtt',
it('Should list these uploaded captions', async function () {
for (const server of servers) {
- const res = await listVideoCaptions(server.url, videoUUID)
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await server.captions.list({ videoId: videoUUID })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
- const caption1: VideoCaption = res.body.data[0]
+ const caption1 = body.data[0]
expect(caption1.language.id).to.equal('ar')
expect(caption1.language.label).to.equal('Arabic')
expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
await testCaptionFile(server.url, caption1.captionPath, 'Subtitle good 1.')
- const caption2: VideoCaption = res.body.data[1]
+ const caption2 = body.data[1]
expect(caption2.language.id).to.equal('zh')
expect(caption2.language.label).to.equal('Chinese')
expect(caption2.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-zh.vtt$'))
it('Should replace an existing caption', async function () {
this.timeout(30000)
- await createVideoCaption({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].captions.add({
language: 'ar',
videoId: videoUUID,
fixture: 'subtitle-good2.vtt'
it('Should have this caption updated', async function () {
for (const server of servers) {
- const res = await listVideoCaptions(server.url, videoUUID)
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await server.captions.list({ videoId: videoUUID })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
- const caption1: VideoCaption = res.body.data[0]
+ const caption1 = body.data[0]
expect(caption1.language.id).to.equal('ar')
expect(caption1.language.label).to.equal('Arabic')
expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
it('Should replace an existing caption with a srt file and convert it', async function () {
this.timeout(30000)
- await createVideoCaption({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].captions.add({
language: 'ar',
videoId: videoUUID,
fixture: 'subtitle-good.srt'
it('Should have this caption updated and converted', async function () {
for (const server of servers) {
- const res = await listVideoCaptions(server.url, videoUUID)
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const body = await server.captions.list({ videoId: videoUUID })
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(2)
- const caption1: VideoCaption = res.body.data[0]
+ const caption1 = body.data[0]
expect(caption1.language.id).to.equal('ar')
expect(caption1.language.label).to.equal('Arabic')
expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
it('Should remove one caption', async function () {
this.timeout(30000)
- await deleteVideoCaption(servers[0].url, servers[0].accessToken, videoUUID, 'ar')
+ await servers[0].captions.delete({ videoId: videoUUID, language: 'ar' })
await waitJobs(servers)
})
it('Should only list the caption that was not deleted', async function () {
for (const server of servers) {
- const res = await listVideoCaptions(server.url, videoUUID)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await server.captions.list({ videoId: videoUUID })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const caption: VideoCaption = res.body.data[0]
+ const caption = body.data[0]
expect(caption.language.id).to.equal('zh')
expect(caption.language.label).to.equal('Chinese')
})
it('Should remove the video, and thus all video captions', async function () {
- await removeVideo(servers[0].url, servers[0].accessToken, videoUUID)
+ const video = await servers[0].videos.get({ id: videoUUID })
+ const { data: captions } = await servers[0].captions.list({ videoId: videoUUID })
+
+ await servers[0].videos.remove({ id: videoUUID })
- await checkVideoFilesWereRemoved(videoUUID, 1)
+ await checkVideoFilesWereRemoved({ server: servers[0], video, captions })
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- acceptChangeOwnership,
- changeVideoOwnership,
+ ChangeOwnershipCommand,
cleanupTests,
- createLive,
- createUser,
+ createMultipleServers,
+ createSingleServer,
doubleFollow,
- flushAndRunMultipleServers,
- flushAndRunServer,
- getMyUserInformation,
- getVideo,
- getVideoChangeOwnershipList,
- getVideosList,
- refuseChangeOwnership,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateCustomSubConfig,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { User } from '../../../../shared/models/users'
-import { VideoDetails, VideoPrivacy } from '../../../../shared/models/videos'
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test video change ownership - nominal', function () {
- let servers: ServerInfo[] = []
- const firstUser = {
- username: 'first',
- password: 'My great password'
- }
- const secondUser = {
- username: 'second',
- password: 'My other password'
- }
-
- let firstUserAccessToken = ''
+ let servers: PeerTubeServer[] = []
+
+ const firstUser = 'first'
+ const secondUser = 'second'
+
+ let firstUserToken = ''
let firstUserChannelId: number
- let secondUserAccessToken = ''
+ let secondUserToken = ''
let secondUserChannelId: number
- let lastRequestChangeOwnershipId = ''
+ let lastRequestId: number
let liveId: number
+ let command: ChangeOwnershipCommand
+
before(async function () {
this.timeout(50000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- enabled: false
- },
- live: {
- enabled: true
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: false
+ },
+ live: {
+ enabled: true
+ }
}
})
- const videoQuota = 42000000
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: firstUser.username,
- password: firstUser.password,
- videoQuota: videoQuota
- })
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: secondUser.username,
- password: secondUser.password,
- videoQuota: videoQuota
- })
-
- firstUserAccessToken = await userLogin(servers[0], firstUser)
- secondUserAccessToken = await userLogin(servers[0], secondUser)
+ firstUserToken = await servers[0].users.generateUserAndToken(firstUser)
+ secondUserToken = await servers[0].users.generateUserAndToken(secondUser)
{
- const res = await getMyUserInformation(servers[0].url, firstUserAccessToken)
- const firstUserInformation: User = res.body
- firstUserChannelId = firstUserInformation.videoChannels[0].id
+ const { videoChannels } = await servers[0].users.getMyInfo({ token: firstUserToken })
+ firstUserChannelId = videoChannels[0].id
}
{
- const res = await getMyUserInformation(servers[0].url, secondUserAccessToken)
- const secondUserInformation: User = res.body
- secondUserChannelId = secondUserInformation.videoChannels[0].id
+ const { videoChannels } = await servers[0].users.getMyInfo({ token: secondUserToken })
+ secondUserChannelId = videoChannels[0].id
}
{
- const videoAttributes = {
+ const attributes = {
name: 'my super name',
description: 'my super description'
}
- const res = await uploadVideo(servers[0].url, firstUserAccessToken, videoAttributes)
+ const { id } = await servers[0].videos.upload({ token: firstUserToken, attributes })
- const resVideo = await getVideo(servers[0].url, res.body.video.id)
- servers[0].video = resVideo.body
+ servers[0].store.videoCreated = await servers[0].videos.get({ id })
}
{
const attributes = { name: 'live', channelId: firstUserChannelId, privacy: VideoPrivacy.PUBLIC }
- const res = await createLive(servers[0].url, firstUserAccessToken, attributes)
+ const video = await servers[0].live.create({ token: firstUserToken, fields: attributes })
- liveId = res.body.video.id
+ liveId = video.id
}
+ command = servers[0].changeOwnership
+
await doubleFollow(servers[0], servers[1])
})
it('Should not have video change ownership', async function () {
- const resFirstUser = await getVideoChangeOwnershipList(servers[0].url, firstUserAccessToken)
+ {
+ const body = await command.list({ token: firstUserToken })
- expect(resFirstUser.body.total).to.equal(0)
- expect(resFirstUser.body.data).to.be.an('array')
- expect(resFirstUser.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
- const resSecondUser = await getVideoChangeOwnershipList(servers[0].url, secondUserAccessToken)
+ {
+ const body = await command.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(0)
- expect(resSecondUser.body.data).to.be.an('array')
- expect(resSecondUser.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
})
it('Should send a request to change ownership of a video', async function () {
this.timeout(15000)
- await changeVideoOwnership(servers[0].url, firstUserAccessToken, servers[0].video.id, secondUser.username)
+ await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
})
it('Should only return a request to change ownership for the second user', async function () {
- const resFirstUser = await getVideoChangeOwnershipList(servers[0].url, firstUserAccessToken)
+ {
+ const body = await command.list({ token: firstUserToken })
- expect(resFirstUser.body.total).to.equal(0)
- expect(resFirstUser.body.data).to.be.an('array')
- expect(resFirstUser.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
- const resSecondUser = await getVideoChangeOwnershipList(servers[0].url, secondUserAccessToken)
+ {
+ const body = await command.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(1)
- expect(resSecondUser.body.data).to.be.an('array')
- expect(resSecondUser.body.data.length).to.equal(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(1)
- lastRequestChangeOwnershipId = resSecondUser.body.data[0].id
+ lastRequestId = body.data[0].id
+ }
})
it('Should accept the same change ownership request without crashing', async function () {
this.timeout(10000)
- await changeVideoOwnership(servers[0].url, firstUserAccessToken, servers[0].video.id, secondUser.username)
+ await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
})
it('Should not create multiple change ownership requests while one is waiting', async function () {
this.timeout(10000)
- const resSecondUser = await getVideoChangeOwnershipList(servers[0].url, secondUserAccessToken)
+ const body = await command.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(1)
- expect(resSecondUser.body.data).to.be.an('array')
- expect(resSecondUser.body.data.length).to.equal(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(1)
})
it('Should not be possible to refuse the change of ownership from first user', async function () {
this.timeout(10000)
- await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, HttpStatusCode.FORBIDDEN_403)
+ await command.refuse({ token: firstUserToken, ownershipId: lastRequestId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should be possible to refuse the change of ownership from second user', async function () {
this.timeout(10000)
- await refuseChangeOwnership(servers[0].url, secondUserAccessToken, lastRequestChangeOwnershipId)
+ await command.refuse({ token: secondUserToken, ownershipId: lastRequestId })
})
it('Should send a new request to change ownership of a video', async function () {
this.timeout(15000)
- await changeVideoOwnership(servers[0].url, firstUserAccessToken, servers[0].video.id, secondUser.username)
+ await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
})
it('Should return two requests to change ownership for the second user', async function () {
- const resFirstUser = await getVideoChangeOwnershipList(servers[0].url, firstUserAccessToken)
+ {
+ const body = await command.list({ token: firstUserToken })
- expect(resFirstUser.body.total).to.equal(0)
- expect(resFirstUser.body.data).to.be.an('array')
- expect(resFirstUser.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
- const resSecondUser = await getVideoChangeOwnershipList(servers[0].url, secondUserAccessToken)
+ {
+ const body = await command.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(2)
- expect(resSecondUser.body.data).to.be.an('array')
- expect(resSecondUser.body.data.length).to.equal(2)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(2)
- lastRequestChangeOwnershipId = resSecondUser.body.data[0].id
+ lastRequestId = body.data[0].id
+ }
})
it('Should not be possible to accept the change of ownership from first user', async function () {
this.timeout(10000)
- await acceptChangeOwnership(
- servers[0].url,
- firstUserAccessToken,
- lastRequestChangeOwnershipId,
- secondUserChannelId,
- HttpStatusCode.FORBIDDEN_403
- )
+ await command.accept({
+ token: firstUserToken,
+ ownershipId: lastRequestId,
+ channelId: secondUserChannelId,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should be possible to accept the change of ownership from second user', async function () {
this.timeout(10000)
- await acceptChangeOwnership(servers[0].url, secondUserAccessToken, lastRequestChangeOwnershipId, secondUserChannelId)
+ await command.accept({ token: secondUserToken, ownershipId: lastRequestId, channelId: secondUserChannelId })
await waitJobs(servers)
})
it('Should have the channel of the video updated', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, servers[0].video.uuid)
-
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
expect(video.name).to.equal('my super name')
expect(video.channel.displayName).to.equal('Main second channel')
it('Should send a request to change ownership of a live', async function () {
this.timeout(15000)
- await changeVideoOwnership(servers[0].url, firstUserAccessToken, liveId, secondUser.username)
+ await command.create({ token: firstUserToken, videoId: liveId, username: secondUser })
- const resSecondUser = await getVideoChangeOwnershipList(servers[0].url, secondUserAccessToken)
+ const body = await command.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(3)
- expect(resSecondUser.body.data.length).to.equal(3)
+ expect(body.total).to.equal(3)
+ expect(body.data.length).to.equal(3)
- lastRequestChangeOwnershipId = resSecondUser.body.data[0].id
+ lastRequestId = body.data[0].id
})
it('Should accept a live ownership change', async function () {
this.timeout(20000)
- await acceptChangeOwnership(servers[0].url, secondUserAccessToken, lastRequestChangeOwnershipId, secondUserChannelId)
+ await command.accept({ token: secondUserToken, ownershipId: lastRequestId, channelId: secondUserChannelId })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, servers[0].video.uuid)
-
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
expect(video.name).to.equal('my super name')
expect(video.channel.displayName).to.equal('Main second channel')
})
describe('Test video change ownership - quota too small', function () {
- let server: ServerInfo
- const firstUser = {
- username: 'first',
- password: 'My great password'
- }
- const secondUser = {
- username: 'second',
- password: 'My other password'
- }
- let firstUserAccessToken = ''
- let secondUserAccessToken = ''
- let lastRequestChangeOwnershipId = ''
+ let server: PeerTubeServer
+ const firstUser = 'first'
+ const secondUser = 'second'
+
+ let firstUserToken = ''
+ let secondUserToken = ''
+ let lastRequestId: number
before(async function () {
this.timeout(50000)
// Run one server
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- const videoQuota = 42000000
- const limitedVideoQuota = 10
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: firstUser.username,
- password: firstUser.password,
- videoQuota: videoQuota
- })
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: secondUser.username,
- password: secondUser.password,
- videoQuota: limitedVideoQuota
- })
+ await server.users.create({ username: secondUser, videoQuota: 10 })
- firstUserAccessToken = await userLogin(server, firstUser)
- secondUserAccessToken = await userLogin(server, secondUser)
+ firstUserToken = await server.users.generateUserAndToken(firstUser)
+ secondUserToken = await server.login.getAccessToken(secondUser)
// Upload some videos on the server
- const video1Attributes = {
+ const attributes = {
name: 'my super name',
description: 'my super description'
}
- await uploadVideo(server.url, firstUserAccessToken, video1Attributes)
+ await server.videos.upload({ token: firstUserToken, attributes })
await waitJobs(server)
- const res = await getVideosList(server.url)
- const videos = res.body.data
-
- expect(videos.length).to.equal(1)
+ const { data } = await server.videos.list()
+ expect(data.length).to.equal(1)
- server.video = videos.find(video => video.name === 'my super name')
+ server.store.videoCreated = data.find(video => video.name === 'my super name')
})
it('Should send a request to change ownership of a video', async function () {
this.timeout(15000)
- await changeVideoOwnership(server.url, firstUserAccessToken, server.video.id, secondUser.username)
+ await server.changeOwnership.create({ token: firstUserToken, videoId: server.store.videoCreated.id, username: secondUser })
})
it('Should only return a request to change ownership for the second user', async function () {
- const resFirstUser = await getVideoChangeOwnershipList(server.url, firstUserAccessToken)
+ {
+ const body = await server.changeOwnership.list({ token: firstUserToken })
- expect(resFirstUser.body.total).to.equal(0)
- expect(resFirstUser.body.data).to.be.an('array')
- expect(resFirstUser.body.data.length).to.equal(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(0)
+ }
- const resSecondUser = await getVideoChangeOwnershipList(server.url, secondUserAccessToken)
+ {
+ const body = await server.changeOwnership.list({ token: secondUserToken })
- expect(resSecondUser.body.total).to.equal(1)
- expect(resSecondUser.body.data).to.be.an('array')
- expect(resSecondUser.body.data.length).to.equal(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data.length).to.equal(1)
- lastRequestChangeOwnershipId = resSecondUser.body.data[0].id
+ lastRequestId = body.data[0].id
+ }
})
it('Should not be possible to accept the change of ownership from second user because of exceeded quota', async function () {
this.timeout(10000)
- const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken)
- const secondUserInformation: User = secondUserInformationResponse.body
- const channelId = secondUserInformation.videoChannels[0].id
+ const { videoChannels } = await server.users.getMyInfo({ token: secondUserToken })
+ const channelId = videoChannels[0].id
- await acceptChangeOwnership(
- server.url,
- secondUserAccessToken,
- lastRequestChangeOwnershipId,
+ await server.changeOwnership.accept({
+ token: secondUserToken,
+ ownershipId: lastRequestId,
channelId,
- HttpStatusCode.PAYLOAD_TOO_LARGE_413
- )
+ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413
+ })
})
after(async function () {
import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
import {
cleanupTests,
- createUser,
- deleteVideoChannelImage,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getActorImage,
- getVideo,
- getVideoChannel,
- getVideoChannelVideos,
+ PeerTubeServer,
+ setAccessTokensToServers,
setDefaultVideoChannel,
testFileExistsOrNot,
testImage,
- updateVideo,
- updateVideoChannelImage,
- uploadVideo,
- userLogin,
- wait
-} from '../../../../shared/extra-utils'
-import {
- addVideoChannel,
- deleteVideoChannel,
- getAccountVideoChannelsList,
- getMyUserInformation,
- getVideoChannelsList,
- ServerInfo,
- setAccessTokensToServers,
- updateVideoChannel,
- viewVideo
-} from '../../../../shared/extra-utils/index'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/index'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { User, VideoChannel } from '@shared/models'
const expect = chai.expect
-async function findChannel (server: ServerInfo, channelId: number) {
- const res = await getVideoChannelsList(server.url, 0, 5, '-name')
- const videoChannel = res.body.data.find(c => c.id === channelId)
+async function findChannel (server: PeerTubeServer, channelId: number) {
+ const body = await server.channels.list({ sort: '-name' })
- return videoChannel as VideoChannel
+ return body.data.find(c => c.id === channelId)
}
describe('Test video channels', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let userInfo: User
let secondVideoChannelId: number
let totoChannel: number
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
})
it('Should have one video channel (created with root)', async () => {
- const res = await getVideoChannelsList(servers[0].url, 0, 2)
+ const body = await servers[0].channels.list({ start: 0, count: 2 })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
})
it('Should create another video channel', async function () {
description: 'super video channel description',
support: 'super video channel support text'
}
- const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
- secondVideoChannelId = res.body.videoChannel.id
+ const created = await servers[0].channels.create({ attributes: videoChannel })
+ secondVideoChannelId = created.id
}
// The channel is 1 is propagated to servers 2
{
- const videoAttributesArg = { name: 'my video name', channelId: secondVideoChannelId, support: 'video support field' }
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributesArg)
- videoUUID = res.body.video.uuid
+ const attributes = { name: 'my video name', channelId: secondVideoChannelId, support: 'video support field' }
+ const { uuid } = await servers[0].videos.upload({ attributes })
+ videoUUID = uuid
}
await waitJobs(servers)
})
it('Should have two video channels when getting my information', async () => {
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- userInfo = res.body
+ userInfo = await servers[0].users.getMyInfo()
expect(userInfo.videoChannels).to.be.an('array')
expect(userInfo.videoChannels).to.have.lengthOf(2)
})
it('Should have two video channels when getting account channels on server 1', async function () {
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName
- })
+ const body = await servers[0].channels.listByAccount({ accountName })
+ expect(body.total).to.equal(2)
+
+ const videoChannels = body.data
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(2)
+ expect(videoChannels).to.be.an('array')
+ expect(videoChannels).to.have.lengthOf(2)
- const videoChannels = res.body.data
expect(videoChannels[0].name).to.equal('root_channel')
expect(videoChannels[0].displayName).to.equal('Main root channel')
it('Should paginate and sort account channels', async function () {
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
+ const body = await servers[0].channels.listByAccount({
accountName,
start: 0,
count: 1,
sort: 'createdAt'
})
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(1)
- const videoChannel: VideoChannel = res.body.data[0]
+ const videoChannel: VideoChannel = body.data[0]
expect(videoChannel.name).to.equal('root_channel')
}
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
+ const body = await servers[0].channels.listByAccount({
accountName,
start: 0,
count: 1,
sort: '-createdAt'
})
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(1)
-
- const videoChannel: VideoChannel = res.body.data[0]
- expect(videoChannel.name).to.equal('second_video_channel')
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('second_video_channel')
}
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
+ const body = await servers[0].channels.listByAccount({
accountName,
start: 1,
count: 1,
sort: '-createdAt'
})
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(1)
-
- const videoChannel: VideoChannel = res.body.data[0]
- expect(videoChannel.name).to.equal('root_channel')
+ expect(body.total).to.equal(2)
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('root_channel')
}
})
it('Should have one video channel when getting account channels on server 2', async function () {
- const res = await getAccountVideoChannelsList({
- url: servers[1].url,
- accountName
- })
+ const body = await servers[1].channels.listByAccount({ accountName })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
- const videoChannels = res.body.data
- expect(videoChannels[0].name).to.equal('second_video_channel')
- expect(videoChannels[0].displayName).to.equal('second video channel')
- expect(videoChannels[0].description).to.equal('super video channel description')
- expect(videoChannels[0].support).to.equal('super video channel support text')
+ const videoChannel = body.data[0]
+ expect(videoChannel.name).to.equal('second_video_channel')
+ expect(videoChannel.displayName).to.equal('second video channel')
+ expect(videoChannel.description).to.equal('super video channel description')
+ expect(videoChannel.support).to.equal('super video channel support text')
})
it('Should list video channels', async function () {
- const res = await getVideoChannelsList(servers[0].url, 1, 1, '-name')
+ const body = await servers[0].channels.list({ start: 1, count: 1, sort: '-name' })
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('root_channel')
- expect(res.body.data[0].displayName).to.equal('Main root channel')
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].name).to.equal('root_channel')
+ expect(body.data[0].displayName).to.equal('Main root channel')
})
it('Should update video channel', async function () {
support: 'support updated'
}
- await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
+ await servers[0].channels.update({ channelName: 'second_video_channel', attributes: videoChannelAttributes })
await waitJobs(servers)
})
it('Should have video channel updated', async function () {
for (const server of servers) {
- const res = await getVideoChannelsList(server.url, 0, 1, '-name')
-
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].name).to.equal('second_video_channel')
- expect(res.body.data[0].displayName).to.equal('video channel updated')
- expect(res.body.data[0].description).to.equal('video channel description updated')
- expect(res.body.data[0].support).to.equal('support updated')
+ const body = await server.channels.list({ start: 0, count: 1, sort: '-name' })
+
+ expect(body.total).to.equal(2)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+
+ expect(body.data[0].name).to.equal('second_video_channel')
+ expect(body.data[0].displayName).to.equal('video channel updated')
+ expect(body.data[0].description).to.equal('video channel description updated')
+ expect(body.data[0].support).to.equal('support updated')
}
})
it('Should not have updated the video support field', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
-
+ const video = await server.videos.get({ id: videoUUID })
expect(video.support).to.equal('video support field')
}
})
bulkVideosSupportUpdate: true
}
- await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
+ await servers[0].channels.update({ channelName: 'second_video_channel', attributes: videoChannelAttributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
-
+ const video = await server.videos.get({ id: videoUUID })
expect(video.support).to.equal(videoChannelAttributes.support)
}
})
const fixture = 'avatar.png'
- await updateVideoChannelImage({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoChannelName: 'second_video_channel',
+ await servers[0].channels.updateImage({
+ channelName: 'second_video_channel',
fixture,
type: 'avatar'
})
await testImage(server.url, 'avatar-resized', avatarPaths[server.port], '.png')
await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), true)
- const row = await getActorImage(server.internalServerNumber, basename(avatarPaths[server.port]))
+ const row = await server.sql.getActorImage(basename(avatarPaths[server.port]))
expect(row.height).to.equal(ACTOR_IMAGES_SIZE.AVATARS.height)
expect(row.width).to.equal(ACTOR_IMAGES_SIZE.AVATARS.width)
}
const fixture = 'banner.jpg'
- await updateVideoChannelImage({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoChannelName: 'second_video_channel',
+ await servers[0].channels.updateImage({
+ channelName: 'second_video_channel',
fixture,
type: 'banner'
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideoChannel(server.url, 'second_video_channel@' + servers[0].host)
- const videoChannel = res.body
+ const videoChannel = await server.channels.get({ channelName: 'second_video_channel@' + servers[0].host })
bannerPaths[server.port] = videoChannel.banner.path
await testImage(server.url, 'banner-resized', bannerPaths[server.port])
await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), true)
- const row = await getActorImage(server.internalServerNumber, basename(bannerPaths[server.port]))
+ const row = await server.sql.getActorImage(basename(bannerPaths[server.port]))
expect(row.height).to.equal(ACTOR_IMAGES_SIZE.BANNERS.height)
expect(row.width).to.equal(ACTOR_IMAGES_SIZE.BANNERS.width)
}
it('Should delete the video channel avatar', async function () {
this.timeout(15000)
- await deleteVideoChannelImage({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoChannelName: 'second_video_channel',
- type: 'avatar'
- })
+ await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'avatar' })
await waitJobs(servers)
it('Should delete the video channel banner', async function () {
this.timeout(15000)
- await deleteVideoChannelImage({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- videoChannelName: 'second_video_channel',
- type: 'banner'
- })
+ await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'banner' })
await waitJobs(servers)
for (const server of servers) {
const channelURI = 'second_video_channel@localhost:' + servers[0].port
- const res1 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5)
- expect(res1.body.total).to.equal(1)
- expect(res1.body.data).to.be.an('array')
- expect(res1.body.data).to.have.lengthOf(1)
- expect(res1.body.data[0].name).to.equal('my video name')
+ const { total, data } = await server.videos.listByChannel({ handle: channelURI })
+
+ expect(total).to.equal(1)
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('my video name')
}
})
it('Should change the video channel of a video', async function () {
this.timeout(10000)
- await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, { channelId: servers[0].videoChannel.id })
+ await servers[0].videos.update({ id: videoUUID, attributes: { channelId: servers[0].store.channel.id } })
await waitJobs(servers)
})
this.timeout(10000)
for (const server of servers) {
- const secondChannelURI = 'second_video_channel@localhost:' + servers[0].port
- const res1 = await getVideoChannelVideos(server.url, server.accessToken, secondChannelURI, 0, 5)
- expect(res1.body.total).to.equal(0)
-
- const channelURI = 'root_channel@localhost:' + servers[0].port
- const res2 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5)
- expect(res2.body.total).to.equal(1)
-
- const videos: Video[] = res2.body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('my video name')
+ {
+ const secondChannelURI = 'second_video_channel@localhost:' + servers[0].port
+ const { total } = await server.videos.listByChannel({ handle: secondChannelURI })
+ expect(total).to.equal(0)
+ }
+
+ {
+ const channelURI = 'root_channel@localhost:' + servers[0].port
+ const { total, data } = await server.videos.listByChannel({ handle: channelURI })
+ expect(total).to.equal(1)
+
+ expect(data).to.be.an('array')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('my video name')
+ }
}
})
it('Should delete video channel', async function () {
- await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel')
+ await servers[0].channels.delete({ channelName: 'second_video_channel' })
})
it('Should have video channel deleted', async function () {
- const res = await getVideoChannelsList(servers[0].url, 0, 10)
+ const body = await servers[0].channels.list({ start: 0, count: 10 })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
- expect(res.body.data[0].displayName).to.equal('Main root channel')
+ expect(body.total).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
+ expect(body.data[0].displayName).to.equal('Main root channel')
})
it('Should create the main channel with an uuid if there is a conflict', async function () {
{
const videoChannel = { name: 'toto_channel', displayName: 'My toto channel' }
- const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
- totoChannel = res.body.videoChannel.id
+ const created = await servers[0].channels.create({ attributes: videoChannel })
+ totoChannel = created.id
}
{
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: 'toto', password: 'password' })
- const accessToken = await userLogin(servers[0], { username: 'toto', password: 'password' })
+ await servers[0].users.create({ username: 'toto', password: 'password' })
+ const accessToken = await servers[0].login.getAccessToken({ username: 'toto', password: 'password' })
- const res = await getMyUserInformation(servers[0].url, accessToken)
- const videoChannel = res.body.videoChannels[0]
+ const { videoChannels } = await servers[0].users.getMyInfo({ token: accessToken })
+ const videoChannel = videoChannels[0]
expect(videoChannel.name).to.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/)
}
})
this.timeout(10000)
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName,
- withStats: true
- })
-
- const channels: VideoChannel[] = res.body.data
+ const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
- for (const channel of channels) {
+ for (const channel of data) {
expect(channel).to.haveOwnProperty('viewsPerDay')
expect(channel.viewsPerDay).to.have.length(30 + 1) // daysPrior + today
}
{
- // video has been posted on channel servers[0].videoChannel.id since last update
- await viewVideo(servers[0].url, videoUUID, 204, '0.0.0.1,127.0.0.1')
- await viewVideo(servers[0].url, videoUUID, 204, '0.0.0.2,127.0.0.1')
+ // video has been posted on channel servers[0].store.videoChannel.id since last update
+ await servers[0].videos.view({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1' })
+ await servers[0].videos.view({ id: videoUUID, xForwardedFor: '0.0.0.2,127.0.0.1' })
// Wait the repeatable job
await wait(8000)
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName,
- withStats: true
- })
- const channelWithView = res.body.data.find((channel: VideoChannel) => channel.id === servers[0].videoChannel.id)
+ const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
+ const channelWithView = data.find(channel => channel.id === servers[0].store.channel.id)
expect(channelWithView.viewsPerDay.slice(-1)[0].views).to.equal(2)
}
})
it('Should report correct videos count', async function () {
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName,
- withStats: true
- })
- const channels: VideoChannel[] = res.body.data
+ const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
- const totoChannel = channels.find(c => c.name === 'toto_channel')
- const rootChannel = channels.find(c => c.name === 'root_channel')
+ const totoChannel = data.find(c => c.name === 'toto_channel')
+ const rootChannel = data.find(c => c.name === 'root_channel')
expect(rootChannel.videosCount).to.equal(1)
expect(totoChannel.videosCount).to.equal(0)
it('Should search among account video channels', async function () {
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName,
- search: 'root'
- })
- expect(res.body.total).to.equal(1)
+ const body = await servers[0].channels.listByAccount({ accountName, search: 'root' })
+ expect(body.total).to.equal(1)
- const channels = res.body.data
+ const channels = body.data
expect(channels).to.have.lengthOf(1)
}
{
- const res = await getAccountVideoChannelsList({
- url: servers[0].url,
- accountName,
- search: 'does not exist'
- })
- expect(res.body.total).to.equal(0)
+ const body = await servers[0].channels.listByAccount({ accountName, search: 'does not exist' })
+ expect(body.total).to.equal(0)
- const channels = res.body.data
+ const channels = body.data
expect(channels).to.have.lengthOf(0)
}
})
it('Should list channels by updatedAt desc if a video has been uploaded', async function () {
this.timeout(30000)
- await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: totoChannel })
+ await servers[0].videos.upload({ attributes: { channelId: totoChannel } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getAccountVideoChannelsList({
- url: server.url,
- accountName,
- sort: '-updatedAt'
- })
+ const { data } = await server.channels.listByAccount({ accountName, sort: '-updatedAt' })
- const channels: VideoChannel[] = res.body.data
- expect(channels[0].name).to.equal('toto_channel')
- expect(channels[1].name).to.equal('root_channel')
+ expect(data[0].name).to.equal('toto_channel')
+ expect(data[1].name).to.equal('root_channel')
}
- await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: servers[0].videoChannel.id })
+ await servers[0].videos.upload({ attributes: { channelId: servers[0].store.channel.id } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getAccountVideoChannelsList({
- url: server.url,
- accountName,
- sort: '-updatedAt'
- })
+ const { data } = await server.channels.listByAccount({ accountName, sort: '-updatedAt' })
- const channels: VideoChannel[] = res.body.data
- expect(channels[0].name).to.equal('root_channel')
- expect(channels[1].name).to.equal('toto_channel')
+ expect(data[0].name).to.equal('root_channel')
+ expect(data[1].name).to.equal('toto_channel')
}
})
import 'mocha'
import * as chai from 'chai'
-import { VideoComment, VideoCommentAdmin, VideoCommentThreadTree } from '@shared/models'
-import { cleanupTests, testImage } from '../../../../shared/extra-utils'
import {
- createUser,
+ cleanupTests,
+ CommentsCommand,
+ createSingleServer,
dateIsValid,
- flushAndRunServer,
- getAccessToken,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateMyAvatar,
- uploadVideo
-} from '../../../../shared/extra-utils/index'
-import {
- addVideoCommentReply,
- addVideoCommentThread,
- deleteVideoComment,
- getAdminVideoComments,
- getVideoCommentThreads,
- getVideoThreadComments
-} from '../../../../shared/extra-utils/videos/video-comments'
+ testImage
+} from '@shared/extra-utils'
const expect = chai.expect
describe('Test video comments', function () {
- let server: ServerInfo
- let videoId
- let videoUUID
- let threadId
+ let server: PeerTubeServer
+ let videoId: number
+ let videoUUID: string
+ let threadId: number
let replyToDeleteId: number
let userAccessTokenServer1: string
+ let command: CommentsCommand
+
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- const res = await uploadVideo(server.url, server.accessToken, {})
- videoUUID = res.body.video.uuid
- videoId = res.body.video.id
+ const { id, uuid } = await server.videos.upload()
+ videoUUID = uuid
+ videoId = id
- await updateMyAvatar({
- url: server.url,
- accessToken: server.accessToken,
- fixture: 'avatar.png'
- })
+ await server.users.updateMyAvatar({ fixture: 'avatar.png' })
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: 'user1',
- password: 'password'
- })
- userAccessTokenServer1 = await getAccessToken(server.url, 'user1', 'password')
+ userAccessTokenServer1 = await server.users.generateUserAndToken('user1')
+
+ command = server.comments
})
describe('User comments', function () {
it('Should not have threads on this video', async function () {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
+ const body = await command.listThreads({ videoId: videoUUID })
- expect(res.body.total).to.equal(0)
- expect(res.body.totalNotDeletedComments).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.totalNotDeletedComments).to.equal(0)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(0)
})
it('Should create a thread in this video', async function () {
const text = 'my super first comment'
- const res = await addVideoCommentThread(server.url, server.accessToken, videoUUID, text)
- const comment = res.body.comment
+ const comment = await command.createThread({ videoId: videoUUID, text })
expect(comment.inReplyToCommentId).to.be.null
expect(comment.text).equal('my super first comment')
})
it('Should list threads of this video', async function () {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
+ const body = await command.listThreads({ videoId: videoUUID })
- expect(res.body.total).to.equal(1)
- expect(res.body.totalNotDeletedComments).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.totalNotDeletedComments).to.equal(1)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(1)
- const comment: VideoComment = res.body.data[0]
+ const comment = body.data[0]
expect(comment.inReplyToCommentId).to.be.null
expect(comment.text).equal('my super first comment')
expect(comment.videoId).to.equal(videoId)
})
it('Should get all the thread created', async function () {
- const res = await getVideoThreadComments(server.url, videoUUID, threadId)
+ const body = await command.getThread({ videoId: videoUUID, threadId })
- const rootComment = res.body.comment
+ const rootComment = body.comment
expect(rootComment.inReplyToCommentId).to.be.null
expect(rootComment.text).equal('my super first comment')
expect(rootComment.videoId).to.equal(videoId)
it('Should create multiple replies in this thread', async function () {
const text1 = 'my super answer to thread 1'
- const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, videoId, threadId, text1)
- const childCommentId = childCommentRes.body.comment.id
+ const created = await command.addReply({ videoId, toCommentId: threadId, text: text1 })
+ const childCommentId = created.id
const text2 = 'my super answer to answer of thread 1'
- await addVideoCommentReply(server.url, server.accessToken, videoId, childCommentId, text2)
+ await command.addReply({ videoId, toCommentId: childCommentId, text: text2 })
const text3 = 'my second answer to thread 1'
- await addVideoCommentReply(server.url, server.accessToken, videoId, threadId, text3)
+ await command.addReply({ videoId, toCommentId: threadId, text: text3 })
})
it('Should get correctly the replies', async function () {
- const res = await getVideoThreadComments(server.url, videoUUID, threadId)
+ const tree = await command.getThread({ videoId: videoUUID, threadId })
- const tree: VideoCommentThreadTree = res.body
expect(tree.comment.text).equal('my super first comment')
expect(tree.children).to.have.lengthOf(2)
it('Should create other threads', async function () {
const text1 = 'super thread 2'
- await addVideoCommentThread(server.url, server.accessToken, videoUUID, text1)
+ await command.createThread({ videoId: videoUUID, text: text1 })
const text2 = 'super thread 3'
- await addVideoCommentThread(server.url, server.accessToken, videoUUID, text2)
+ await command.createThread({ videoId: videoUUID, text: text2 })
})
it('Should list the threads', async function () {
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
-
- expect(res.body.total).to.equal(3)
- expect(res.body.totalNotDeletedComments).to.equal(6)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(3)
-
- expect(res.body.data[0].text).to.equal('my super first comment')
- expect(res.body.data[0].totalReplies).to.equal(3)
- expect(res.body.data[1].text).to.equal('super thread 2')
- expect(res.body.data[1].totalReplies).to.equal(0)
- expect(res.body.data[2].text).to.equal('super thread 3')
- expect(res.body.data[2].totalReplies).to.equal(0)
+ const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
+
+ expect(body.total).to.equal(3)
+ expect(body.totalNotDeletedComments).to.equal(6)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(3)
+
+ expect(body.data[0].text).to.equal('my super first comment')
+ expect(body.data[0].totalReplies).to.equal(3)
+ expect(body.data[1].text).to.equal('super thread 2')
+ expect(body.data[1].totalReplies).to.equal(0)
+ expect(body.data[2].text).to.equal('super thread 3')
+ expect(body.data[2].totalReplies).to.equal(0)
})
it('Should delete a reply', async function () {
- await deleteVideoComment(server.url, server.accessToken, videoId, replyToDeleteId)
+ await command.delete({ videoId, commentId: replyToDeleteId })
{
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
+ const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
- expect(res.body.total).to.equal(3)
- expect(res.body.totalNotDeletedComments).to.equal(5)
+ expect(body.total).to.equal(3)
+ expect(body.totalNotDeletedComments).to.equal(5)
}
{
- const res = await getVideoThreadComments(server.url, videoUUID, threadId)
+ const tree = await command.getThread({ videoId: videoUUID, threadId })
- const tree: VideoCommentThreadTree = res.body
expect(tree.comment.text).equal('my super first comment')
expect(tree.children).to.have.lengthOf(2)
})
it('Should delete a complete thread', async function () {
- await deleteVideoComment(server.url, server.accessToken, videoId, threadId)
-
- const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
- expect(res.body.total).to.equal(3)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data).to.have.lengthOf(3)
-
- expect(res.body.data[0].text).to.equal('')
- expect(res.body.data[0].isDeleted).to.be.true
- expect(res.body.data[0].deletedAt).to.not.be.null
- expect(res.body.data[0].account).to.be.null
- expect(res.body.data[0].totalReplies).to.equal(2)
- expect(res.body.data[1].text).to.equal('super thread 2')
- expect(res.body.data[1].totalReplies).to.equal(0)
- expect(res.body.data[2].text).to.equal('super thread 3')
- expect(res.body.data[2].totalReplies).to.equal(0)
+ await command.delete({ videoId, commentId: threadId })
+
+ const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
+ expect(body.total).to.equal(3)
+ expect(body.data).to.be.an('array')
+ expect(body.data).to.have.lengthOf(3)
+
+ expect(body.data[0].text).to.equal('')
+ expect(body.data[0].isDeleted).to.be.true
+ expect(body.data[0].deletedAt).to.not.be.null
+ expect(body.data[0].account).to.be.null
+ expect(body.data[0].totalReplies).to.equal(2)
+ expect(body.data[1].text).to.equal('super thread 2')
+ expect(body.data[1].totalReplies).to.equal(0)
+ expect(body.data[2].text).to.equal('super thread 3')
+ expect(body.data[2].totalReplies).to.equal(0)
})
it('Should count replies from the video author correctly', async function () {
- const text = 'my super first comment'
- await addVideoCommentThread(server.url, server.accessToken, videoUUID, text)
- let res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
- const comment: VideoComment = res.body.data[0]
- const threadId2 = comment.threadId
+ await command.createThread({ videoId: videoUUID, text: 'my super first comment' })
+
+ const { data } = await command.listThreads({ videoId: videoUUID })
+ const threadId2 = data[0].threadId
const text2 = 'a first answer to thread 4 by a third party'
- await addVideoCommentReply(server.url, userAccessTokenServer1, videoId, threadId2, text2)
+ await command.addReply({ token: userAccessTokenServer1, videoId, toCommentId: threadId2, text: text2 })
const text3 = 'my second answer to thread 4'
- await addVideoCommentReply(server.url, server.accessToken, videoId, threadId2, text3)
+ await command.addReply({ videoId, toCommentId: threadId2, text: text3 })
- res = await getVideoThreadComments(server.url, videoUUID, threadId2)
- const tree: VideoCommentThreadTree = res.body
+ const tree = await command.getThread({ videoId: videoUUID, threadId: threadId2 })
expect(tree.comment.totalReplies).to.equal(tree.comment.totalRepliesFromVideoAuthor + 1)
})
})
describe('All instance comments', function () {
- async function getComments (options: any = {}) {
- const res = await getAdminVideoComments(Object.assign({
- url: server.url,
- token: server.accessToken,
- start: 0,
- count: 10
- }, options))
-
- return { comments: res.body.data as VideoCommentAdmin[], total: res.body.total as number }
- }
it('Should list instance comments as admin', async function () {
- const { comments } = await getComments({ start: 0, count: 1 })
+ const { data } = await command.listForAdmin({ start: 0, count: 1 })
- expect(comments[0].text).to.equal('my second answer to thread 4')
+ expect(data[0].text).to.equal('my second answer to thread 4')
})
it('Should filter instance comments by isLocal', async function () {
- const { total, comments } = await getComments({ isLocal: false })
+ const { total, data } = await command.listForAdmin({ isLocal: false })
- expect(comments).to.have.lengthOf(0)
+ expect(data).to.have.lengthOf(0)
expect(total).to.equal(0)
})
it('Should search instance comments by account', async function () {
- const { total, comments } = await getComments({ searchAccount: 'user' })
+ const { total, data } = await command.listForAdmin({ searchAccount: 'user' })
- expect(comments).to.have.lengthOf(1)
+ expect(data).to.have.lengthOf(1)
expect(total).to.equal(1)
- expect(comments[0].text).to.equal('a first answer to thread 4 by a third party')
+ expect(data[0].text).to.equal('a first answer to thread 4 by a third party')
})
it('Should search instance comments by video', async function () {
{
- const { total, comments } = await getComments({ searchVideo: 'video' })
+ const { total, data } = await command.listForAdmin({ searchVideo: 'video' })
- expect(comments).to.have.lengthOf(7)
+ expect(data).to.have.lengthOf(7)
expect(total).to.equal(7)
}
{
- const { total, comments } = await getComments({ searchVideo: 'hello' })
+ const { total, data } = await command.listForAdmin({ searchVideo: 'hello' })
- expect(comments).to.have.lengthOf(0)
+ expect(data).to.have.lengthOf(0)
expect(total).to.equal(0)
}
})
it('Should search instance comments', async function () {
- const { total, comments } = await getComments({ search: 'super thread 3' })
+ const { total, data } = await command.listForAdmin({ search: 'super thread 3' })
- expect(comments).to.have.lengthOf(1)
expect(total).to.equal(1)
- expect(comments[0].text).to.equal('super thread 3')
+
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].text).to.equal('super thread 3')
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import {
- cleanupTests,
- flushAndRunMultipleServers,
- getVideo,
- getVideoDescription,
- getVideosList,
- ServerInfo,
- setAccessTokensToServers,
- updateVideo,
- uploadVideo
-} from '../../../../shared/extra-utils/index'
-import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+import * as chai from 'chai'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
const expect = chai.expect
describe('Test video description', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID = ''
let videoId: number
const longDescription = 'my super description for server 1'.repeat(50)
this.timeout(40000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
// Get the access tokens
await setAccessTokensToServers(servers)
const attributes = {
description: longDescription
}
- await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
+ await servers[0].videos.upload({ attributes })
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
+ const { data } = await servers[0].videos.list()
- videoId = res.body.data[0].id
- videoUUID = res.body.data[0].uuid
+ videoId = data[0].id
+ videoUUID = data[0].uuid
})
it('Should have a truncated description on each server', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video = res.body
+ const video = await server.videos.get({ id: videoUUID })
// 30 characters * 6 -> 240 characters
const truncatedDescription = 'my super description for server 1'.repeat(7) +
it('Should fetch long description on each server', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video = res.body
+ const video = await server.videos.get({ id: videoUUID })
- const res2 = await getVideoDescription(server.url, video.descriptionPath)
- expect(res2.body.description).to.equal(longDescription)
+ const { description } = await server.videos.getDescription({ descriptionPath: video.descriptionPath })
+ expect(description).to.equal(longDescription)
}
})
const attributes = {
description: 'short description'
}
- await updateVideo(servers[0].url, servers[0].accessToken, videoId, attributes)
+ await servers[0].videos.update({ id: videoId, attributes })
await waitJobs(servers)
})
it('Should have a small description on each server', async function () {
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video = res.body
+ const video = await server.videos.get({ id: videoUUID })
expect(video.description).to.equal('short description')
- const res2 = await getVideoDescription(server.url, video.descriptionPath)
- expect(res2.body.description).to.equal('short description')
+ const { description } = await server.videos.getDescription({ descriptionPath: video.descriptionPath })
+ expect(description).to.equal('short description')
}
})
import 'mocha'
import * as chai from 'chai'
-import { join } from 'path'
+import { basename, join } from 'path'
+import { removeFragmentedMP4Ext, uuidRegex } from '@shared/core-utils'
import {
checkDirectoryIsEmpty,
checkResolutionsInMasterPlaylist,
checkSegmentHash,
checkTmpIsEmpty,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getPlaylist,
- getVideo,
makeRawRequest,
- removeVideo,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateCustomSubConfig,
- updateVideo,
- uploadVideo,
waitJobs,
webtorrentAdd
-} from '../../../../shared/extra-utils'
-import { VideoDetails } from '../../../../shared/models/videos'
-import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models'
import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const expect = chai.expect
-async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOnly: boolean, resolutions = [ 240, 360, 480, 720 ]) {
+async function checkHlsPlaylist (servers: PeerTubeServer[], videoUUID: string, hlsOnly: boolean, resolutions = [ 240, 360, 480, 720 ]) {
for (const server of servers) {
- const resVideoDetails = await getVideo(server.url, videoUUID)
- const videoDetails: VideoDetails = resVideoDetails.body
+ const videoDetails = await server.videos.get({ id: videoUUID })
const baseUrl = `http://${videoDetails.account.host}`
expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
if (hlsOnly) expect(videoDetails.files).to.have.lengthOf(0)
else expect(videoDetails.files).to.have.lengthOf(resolutions.length)
+ // Check JSON files
for (const resolution of resolutions) {
const file = hlsFiles.find(f => f.resolution.id === resolution)
expect(file).to.not.be.undefined
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.torrentUrl).to.equal(`http://${server.host}/lazy-static/torrents/${videoDetails.uuid}-${file.resolution.id}-hls.torrent`)
- expect(file.fileUrl).to.equal(
- `${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${videoDetails.uuid}-${file.resolution.id}-fragmented.mp4`
+ expect(file.torrentUrl).to.match(
+ new RegExp(`http://${server.host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}-hls.torrent`)
+ )
+ expect(file.fileUrl).to.match(
+ new RegExp(`${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${uuidRegex}-${file.resolution.id}-fragmented.mp4`)
)
expect(file.resolution.label).to.equal(resolution + 'p')
expect(torrent.files[0].path).to.exist.and.to.not.equal('')
}
+ // Check master playlist
{
- await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions)
+ await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions })
- const res = await getPlaylist(hlsPlaylist.playlistUrl)
- const masterPlaylist = res.text
+ const masterPlaylist = await server.streamingPlaylists.get({ url: hlsPlaylist.playlistUrl })
for (const resolution of resolutions) {
expect(masterPlaylist).to.contain(`${resolution}.m3u8`)
}
}
+ // Check resolution playlists
{
for (const resolution of resolutions) {
- const res = await getPlaylist(`${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${resolution}.m3u8`)
+ const file = hlsFiles.find(f => f.resolution.id === resolution)
+ const playlistName = removeFragmentedMP4Ext(basename(file.fileUrl)) + '.m3u8'
+
+ const subPlaylist = await server.streamingPlaylists.get({
+ url: `${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${playlistName}`
+ })
- const subPlaylist = res.text
- expect(subPlaylist).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`)
+ expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`))
+ expect(subPlaylist).to.contain(basename(file.fileUrl))
}
}
const baseUrlAndPath = baseUrl + '/static/streaming-playlists/hls'
for (const resolution of resolutions) {
- await checkSegmentHash(baseUrlAndPath, baseUrlAndPath, videoUUID, resolution, hlsPlaylist)
+ await checkSegmentHash({
+ server,
+ baseUrlPlaylist: baseUrlAndPath,
+ baseUrlSegment: baseUrlAndPath,
+ videoUUID,
+ resolution,
+ hlsPlaylist
+ })
}
}
}
}
describe('Test HLS videos', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let videoUUID = ''
let videoAudioUUID = ''
function runTestSuite (hlsOnly: boolean) {
+
it('Should upload a video and transcode it to HLS', async function () {
this.timeout(120000)
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 1', fixture: 'video_short.webm' })
- videoUUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1', fixture: 'video_short.webm' } })
+ videoUUID = uuid
await waitJobs(servers)
it('Should upload an audio file and transcode it to HLS', async function () {
this.timeout(120000)
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video audio', fixture: 'sample.ogg' })
- videoAudioUUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video audio', fixture: 'sample.ogg' } })
+ videoAudioUUID = uuid
await waitJobs(servers)
it('Should update the video', async function () {
this.timeout(10000)
- await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, { name: 'video 1 updated' })
+ await servers[0].videos.update({ id: videoUUID, attributes: { name: 'video 1 updated' } })
await waitJobs(servers)
it('Should delete videos', async function () {
this.timeout(10000)
- await removeVideo(servers[0].url, servers[0].accessToken, videoUUID)
- await removeVideo(servers[0].url, servers[0].accessToken, videoAudioUUID)
+ await servers[0].videos.remove({ id: videoUUID })
+ await servers[0].videos.remove({ id: videoAudioUUID })
await waitJobs(servers)
for (const server of servers) {
- await getVideo(server.url, videoUUID, HttpStatusCode.NOT_FOUND_404)
- await getVideo(server.url, videoAudioUUID, HttpStatusCode.NOT_FOUND_404)
+ await server.videos.get({ id: videoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
+ await server.videos.get({ id: videoAudioUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
})
}
}
}
- servers = await flushAndRunMultipleServers(2, configOverride)
+ servers = await createMultipleServers(2, configOverride)
// Get the access tokens
await setAccessTokensToServers(servers)
describe('With only HLS enabled', function () {
before(async function () {
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- enabled: true,
- allowAudioFiles: true,
- resolutions: {
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- hls: {
- enabled: true
- },
- webtorrent: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: true,
+ allowAudioFiles: true,
+ resolutions: {
+ '240p': true,
+ '360p': true,
+ '480p': true,
+ '720p': true,
+ '1080p': true,
+ '1440p': true,
+ '2160p': true
+ },
+ hls: {
+ enabled: true
+ },
+ webtorrent: {
+ enabled: false
+ }
}
}
})
import 'mocha'
import * as chai from 'chai'
import {
+ areHttpImportTestsDisabled,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getMyUserInformation,
- getMyVideos,
- getVideo,
- getVideosList,
- immutableAssign,
- listVideoCaptions,
- ServerInfo,
+ FIXTURE_URLS,
+ PeerTubeServer,
setAccessTokensToServers,
testCaptionFile,
- updateCustomSubConfig
-} from '../../../../shared/extra-utils'
-import { areHttpImportTestsDisabled, testImage } from '../../../../shared/extra-utils/miscs/miscs'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import {
- getMagnetURI,
- getMyVideoImports,
- getYoutubeHDRVideoUrl,
- getYoutubeVideoUrl,
- importVideo
-} from '../../../../shared/extra-utils/videos/video-imports'
-import { VideoCaption, VideoDetails, VideoImport, VideoPrivacy, VideoResolution } from '../../../../shared/models/videos'
+ testImage,
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPrivacy, VideoResolution } from '@shared/models'
const expect = chai.expect
describe('Test video imports', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let channelIdServer1: number
let channelIdServer2: number
if (areHttpImportTestsDisabled()) return
- async function checkVideosServer1 (url: string, idHttp: string, idMagnet: string, idTorrent: string) {
- const resHttp = await getVideo(url, idHttp)
- const videoHttp: VideoDetails = resHttp.body
+ async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) {
+ const videoHttp = await server.videos.get({ id: idHttp })
expect(videoHttp.name).to.equal('small video - youtube')
// FIXME: youtube-dl seems broken
expect(originallyPublishedAt.getMonth()).to.equal(0)
expect(originallyPublishedAt.getFullYear()).to.equal(2019)
- const resMagnet = await getVideo(url, idMagnet)
- const videoMagnet: VideoDetails = resMagnet.body
- const resTorrent = await getVideo(url, idTorrent)
- const videoTorrent: VideoDetails = resTorrent.body
+ const videoMagnet = await server.videos.get({ id: idMagnet })
+ const videoTorrent = await server.videos.get({ id: idTorrent })
for (const video of [ videoMagnet, videoTorrent ]) {
expect(video.category.label).to.equal('Misc')
expect(videoTorrent.name).to.contain('你好 世界 720p.mp4')
expect(videoMagnet.name).to.contain('super peertube2 video')
- const resCaptions = await listVideoCaptions(url, idHttp)
- expect(resCaptions.body.total).to.equal(2)
+ const bodyCaptions = await server.captions.list({ videoId: idHttp })
+ expect(bodyCaptions.total).to.equal(2)
}
- async function checkVideoServer2 (url: string, id: number | string) {
- const res = await getVideo(url, id)
- const video: VideoDetails = res.body
+ async function checkVideoServer2 (server: PeerTubeServer, id: number | string) {
+ const video = await server.videos.get({ id })
expect(video.name).to.equal('my super name')
expect(video.category.label).to.equal('Entertainment')
expect(video.files).to.have.lengthOf(1)
- const resCaptions = await listVideoCaptions(url, id)
- expect(resCaptions.body.total).to.equal(2)
+ const bodyCaptions = await server.captions.list({ videoId: id })
+ expect(bodyCaptions.total).to.equal(2)
}
before(async function () {
this.timeout(30_000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
{
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- channelIdServer1 = res.body.videoChannels[0].id
+ const { videoChannels } = await servers[0].users.getMyInfo()
+ channelIdServer1 = videoChannels[0].id
}
{
- const res = await getMyUserInformation(servers[1].url, servers[1].accessToken)
- channelIdServer2 = res.body.videoChannels[0].id
+ const { videoChannels } = await servers[1].users.getMyInfo()
+ channelIdServer2 = videoChannels[0].id
}
await doubleFollow(servers[0], servers[1])
}
{
- const attributes = immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() })
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- expect(res.body.video.name).to.equal('small video - youtube')
+ const attributes = { ...baseAttributes, targetUrl: FIXTURE_URLS.youtube }
+ const { video } = await servers[0].imports.importVideo({ attributes })
+ expect(video.name).to.equal('small video - youtube')
- expect(res.body.video.thumbnailPath).to.match(new RegExp(`^/static/thumbnails/.+.jpg$`))
- expect(res.body.video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`))
+ expect(video.thumbnailPath).to.match(new RegExp(`^/static/thumbnails/.+.jpg$`))
+ expect(video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`))
- await testImage(servers[0].url, 'video_import_thumbnail', res.body.video.thumbnailPath)
- await testImage(servers[0].url, 'video_import_preview', res.body.video.previewPath)
+ await testImage(servers[0].url, 'video_import_thumbnail', video.thumbnailPath)
+ await testImage(servers[0].url, 'video_import_preview', video.previewPath)
- const resCaptions = await listVideoCaptions(servers[0].url, res.body.video.id)
- const videoCaptions: VideoCaption[] = resCaptions.body.data
+ const bodyCaptions = await servers[0].captions.list({ videoId: video.id })
+ const videoCaptions = bodyCaptions.data
expect(videoCaptions).to.have.lengthOf(2)
const enCaption = videoCaptions.find(caption => caption.language.id === 'en')
}
{
- const attributes = immutableAssign(baseAttributes, {
- magnetUri: getMagnetURI(),
+ const attributes = {
+ ...baseAttributes,
+ magnetUri: FIXTURE_URLS.magnet,
description: 'this is a super torrent description',
tags: [ 'tag_torrent1', 'tag_torrent2' ]
- })
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- expect(res.body.video.name).to.equal('super peertube2 video')
+ }
+ const { video } = await servers[0].imports.importVideo({ attributes })
+ expect(video.name).to.equal('super peertube2 video')
}
{
- const attributes = immutableAssign(baseAttributes, {
+ const attributes = {
+ ...baseAttributes,
torrentfile: 'video-720p.torrent' as any,
description: 'this is a super torrent description',
tags: [ 'tag_torrent1', 'tag_torrent2' ]
- })
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- expect(res.body.video.name).to.equal('你好 世界 720p.mp4')
+ }
+ const { video } = await servers[0].imports.importVideo({ attributes })
+ expect(video.name).to.equal('你好 世界 720p.mp4')
}
})
it('Should list the videos to import in my videos on server 1', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5, 'createdAt')
+ const { total, data } = await servers[0].videos.listMyVideos({ sort: 'createdAt' })
- expect(res.body.total).to.equal(3)
+ expect(total).to.equal(3)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(3)
- expect(videos[0].name).to.equal('small video - youtube')
- expect(videos[1].name).to.equal('super peertube2 video')
- expect(videos[2].name).to.equal('你好 世界 720p.mp4')
+ expect(data).to.have.lengthOf(3)
+ expect(data[0].name).to.equal('small video - youtube')
+ expect(data[1].name).to.equal('super peertube2 video')
+ expect(data[2].name).to.equal('你好 世界 720p.mp4')
})
it('Should list the videos to import in my imports on server 1', async function () {
- const res = await getMyVideoImports(servers[0].url, servers[0].accessToken, '-createdAt')
+ const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ sort: '-createdAt' })
+ expect(total).to.equal(3)
- expect(res.body.total).to.equal(3)
- const videoImports: VideoImport[] = res.body.data
expect(videoImports).to.have.lengthOf(3)
- expect(videoImports[2].targetUrl).to.equal(getYoutubeVideoUrl())
+ expect(videoImports[2].targetUrl).to.equal(FIXTURE_URLS.youtube)
expect(videoImports[2].magnetUri).to.be.null
expect(videoImports[2].torrentName).to.be.null
expect(videoImports[2].video.name).to.equal('small video - youtube')
expect(videoImports[1].targetUrl).to.be.null
- expect(videoImports[1].magnetUri).to.equal(getMagnetURI())
+ expect(videoImports[1].magnetUri).to.equal(FIXTURE_URLS.magnet)
expect(videoImports[1].torrentName).to.be.null
expect(videoImports[1].video.name).to.equal('super peertube2 video')
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(3)
- expect(res.body.data).to.have.lengthOf(3)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(3)
+ expect(data).to.have.lengthOf(3)
- const [ videoHttp, videoMagnet, videoTorrent ] = res.body.data
- await checkVideosServer1(server.url, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
+ const [ videoHttp, videoMagnet, videoTorrent ] = data
+ await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
}
})
this.timeout(60_000)
const attributes = {
- targetUrl: getYoutubeVideoUrl(),
+ targetUrl: FIXTURE_URLS.youtube,
channelId: channelIdServer2,
privacy: VideoPrivacy.PUBLIC,
category: 10,
description: 'my super description',
tags: [ 'supertag1', 'supertag2' ]
}
- const res = await importVideo(servers[1].url, servers[1].accessToken, attributes)
- expect(res.body.video.name).to.equal('my super name')
+ const { video } = await servers[1].imports.importVideo({ attributes })
+ expect(video.name).to.equal('my super name')
})
it('Should have the videos listed on the two instances', async function () {
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(4)
- expect(res.body.data).to.have.lengthOf(4)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(4)
+ expect(data).to.have.lengthOf(4)
- await checkVideoServer2(server.url, res.body.data[0].uuid)
+ await checkVideoServer2(server, data[0].uuid)
- const [ , videoHttp, videoMagnet, videoTorrent ] = res.body.data
- await checkVideosServer1(server.url, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
+ const [ , videoHttp, videoMagnet, videoTorrent ] = data
+ await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
}
})
const attributes = {
name: 'transcoded video',
- magnetUri: getMagnetURI(),
+ magnetUri: FIXTURE_URLS.magnet,
channelId: channelIdServer2,
privacy: VideoPrivacy.PUBLIC
}
- const res = await importVideo(servers[1].url, servers[1].accessToken, attributes)
- const videoUUID = res.body.video.uuid
+ const { video } = await servers[1].imports.importVideo({ attributes })
+ const videoUUID = video.uuid
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: videoUUID })
expect(video.name).to.equal('transcoded video')
expect(video.files).to.have.lengthOf(4)
}
}
}
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
const attributes = {
name: 'hdr video',
- targetUrl: getYoutubeHDRVideoUrl(),
+ targetUrl: FIXTURE_URLS.youtubeHDR,
channelId: channelIdServer1,
privacy: VideoPrivacy.PUBLIC
}
- const res1 = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- const videoUUID = res1.body.video.uuid
+ const { video: videoImported } = await servers[0].imports.importVideo({ attributes })
+ const videoUUID = videoImported.uuid
await waitJobs(servers)
// test resolution
- const res2 = await getVideo(servers[0].url, videoUUID)
- const video: VideoDetails = res2.body
+ const video = await servers[0].videos.get({ id: videoUUID })
expect(video.name).to.equal('hdr video')
const maxResolution = Math.max.apply(Math, video.files.map(function (o) { return o.resolution.id }))
expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_1080P)
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { cleanupTests, getVideosList, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../../../shared/extra-utils/index'
-import { userLogin } from '../../../../shared/extra-utils/users/login'
-import { createUser } from '../../../../shared/extra-utils/users/users'
-import { getMyVideos } from '../../../../shared/extra-utils/videos/videos'
-import {
- flushAndRunServer,
- getAccountVideos,
- getConfig,
- getCustomConfig,
- getMyUserInformation,
- getVideoChannelVideos,
- getVideosListWithToken,
- searchVideo,
- searchVideoWithToken,
- updateCustomConfig,
- updateMyUser
-} from '../../../../shared/extra-utils'
-import { ServerConfig, VideosOverview } from '../../../../shared/models'
-import { CustomConfig } from '../../../../shared/models/server/custom-config.model'
-import { User } from '../../../../shared/models/users'
-import { getVideosOverview, getVideosOverviewWithToken } from '@shared/extra-utils/overviews/overviews'
+import * as chai from 'chai'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { BooleanBothQuery, CustomConfig, ResultList, Video, VideosOverview } from '@shared/models'
const expect = chai.expect
-function createOverviewRes (res: any) {
- const overview = res.body as VideosOverview
-
+function createOverviewRes (overview: VideosOverview) {
const videos = overview.categories[0].videos
- return { body: { data: videos, total: videos.length } }
+ return { data: videos, total: videos.length }
}
describe('Test video NSFW policy', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
let customConfig: CustomConfig
- function getVideosFunctions (token?: string, query = {}) {
- return getMyUserInformation(server.url, server.accessToken)
- .then(res => {
- const user: User = res.body
- const videoChannelName = user.videoChannels[0].name
- const accountName = user.account.name + '@' + user.account.host
- const hasQuery = Object.keys(query).length !== 0
- let promises: Promise<any>[]
-
- if (token) {
- promises = [
- getVideosListWithToken(server.url, token, query),
- searchVideoWithToken(server.url, 'n', token, query),
- getAccountVideos(server.url, token, accountName, 0, 5, undefined, query),
- getVideoChannelVideos(server.url, token, videoChannelName, 0, 5, undefined, query)
- ]
-
- // Overviews do not support video filters
- if (!hasQuery) {
- promises.push(getVideosOverviewWithToken(server.url, 1, token).then(res => createOverviewRes(res)))
- }
-
- return Promise.all(promises)
- }
-
- promises = [
- getVideosList(server.url),
- searchVideo(server.url, 'n'),
- getAccountVideos(server.url, undefined, accountName, 0, 5),
- getVideoChannelVideos(server.url, undefined, videoChannelName, 0, 5)
- ]
-
- // Overviews do not support video filters
- if (!hasQuery) {
- promises.push(getVideosOverview(server.url, 1).then(res => createOverviewRes(res)))
- }
-
- return Promise.all(promises)
- })
+ async function getVideosFunctions (token?: string, query: { nsfw?: BooleanBothQuery } = {}) {
+ const user = await server.users.getMyInfo()
+
+ const channelName = user.videoChannels[0].name
+ const accountName = user.account.name + '@' + user.account.host
+
+ const hasQuery = Object.keys(query).length !== 0
+ let promises: Promise<ResultList<Video>>[]
+
+ if (token) {
+ promises = [
+ server.search.advancedVideoSearch({ token, search: { search: 'n', sort: '-publishedAt', ...query } }),
+ server.videos.listWithToken({ token, ...query }),
+ server.videos.listByAccount({ token, handle: accountName, ...query }),
+ server.videos.listByChannel({ token, handle: channelName, ...query })
+ ]
+
+ // Overviews do not support video filters
+ if (!hasQuery) {
+ const p = server.overviews.getVideos({ page: 1, token })
+ .then(res => createOverviewRes(res))
+ promises.push(p)
+ }
+
+ return Promise.all(promises)
+ }
+
+ promises = [
+ server.search.searchVideos({ search: 'n', sort: '-publishedAt' }),
+ server.videos.list(),
+ server.videos.listByAccount({ token: null, handle: accountName }),
+ server.videos.listByChannel({ token: null, handle: channelName })
+ ]
+
+ // Overviews do not support video filters
+ if (!hasQuery) {
+ const p = server.overviews.getVideos({ page: 1 })
+ .then(res => createOverviewRes(res))
+ promises.push(p)
+ }
+
+ return Promise.all(promises)
}
before(async function () {
this.timeout(50000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
// Get the access tokens
await setAccessTokensToServers([ server ])
{
const attributes = { name: 'nsfw', nsfw: true, category: 1 }
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes })
}
{
const attributes = { name: 'normal', nsfw: false, category: 1 }
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes })
}
- {
- const res = await getCustomConfig(server.url, server.accessToken)
- customConfig = res.body
- }
+ customConfig = await server.config.getCustomConfig()
})
describe('Instance default NSFW policy', function () {
+
it('Should display NSFW videos with display default NSFW policy', async function () {
- const resConfig = await getConfig(server.url)
- const serverConfig: ServerConfig = resConfig.body
+ const serverConfig = await server.config.getConfig()
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('display')
- for (const res of await getVideosFunctions()) {
- expect(res.body.total).to.equal(2)
+ for (const body of await getVideosFunctions()) {
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('normal')
expect(videos[1].name).to.equal('nsfw')
it('Should not display NSFW videos with do_not_list default NSFW policy', async function () {
customConfig.instance.defaultNSFWPolicy = 'do_not_list'
- await updateCustomConfig(server.url, server.accessToken, customConfig)
+ await server.config.updateCustomConfig({ newCustomConfig: customConfig })
- const resConfig = await getConfig(server.url)
- const serverConfig: ServerConfig = resConfig.body
+ const serverConfig = await server.config.getConfig()
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('do_not_list')
- for (const res of await getVideosFunctions()) {
- expect(res.body.total).to.equal(1)
+ for (const body of await getVideosFunctions()) {
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('normal')
}
it('Should display NSFW videos with blur default NSFW policy', async function () {
customConfig.instance.defaultNSFWPolicy = 'blur'
- await updateCustomConfig(server.url, server.accessToken, customConfig)
+ await server.config.updateCustomConfig({ newCustomConfig: customConfig })
- const resConfig = await getConfig(server.url)
- const serverConfig: ServerConfig = resConfig.body
+ const serverConfig = await server.config.getConfig()
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('blur')
- for (const res of await getVideosFunctions()) {
- expect(res.body.total).to.equal(2)
+ for (const body of await getVideosFunctions()) {
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('normal')
expect(videos[1].name).to.equal('nsfw')
it('Should create a user having the default nsfw policy', async function () {
const username = 'user1'
const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
-
- userAccessToken = await userLogin(server, { username, password })
+ await server.users.create({ username: username, password: password })
- const res = await getMyUserInformation(server.url, userAccessToken)
- const user = res.body
+ userAccessToken = await server.login.getAccessToken({ username, password })
+ const user = await server.users.getMyInfo({ token: userAccessToken })
expect(user.nsfwPolicy).to.equal('blur')
})
it('Should display NSFW videos with blur user NSFW policy', async function () {
customConfig.instance.defaultNSFWPolicy = 'do_not_list'
- await updateCustomConfig(server.url, server.accessToken, customConfig)
+ await server.config.updateCustomConfig({ newCustomConfig: customConfig })
- for (const res of await getVideosFunctions(userAccessToken)) {
- expect(res.body.total).to.equal(2)
+ for (const body of await getVideosFunctions(userAccessToken)) {
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('normal')
expect(videos[1].name).to.equal('nsfw')
})
it('Should display NSFW videos with display user NSFW policy', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: server.accessToken,
- nsfwPolicy: 'display'
- })
+ await server.users.updateMe({ nsfwPolicy: 'display' })
- for (const res of await getVideosFunctions(server.accessToken)) {
- expect(res.body.total).to.equal(2)
+ for (const body of await getVideosFunctions(server.accessToken)) {
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('normal')
expect(videos[1].name).to.equal('nsfw')
})
it('Should not display NSFW videos with do_not_list user NSFW policy', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: server.accessToken,
- nsfwPolicy: 'do_not_list'
- })
+ await server.users.updateMe({ nsfwPolicy: 'do_not_list' })
- for (const res of await getVideosFunctions(server.accessToken)) {
- expect(res.body.total).to.equal(1)
+ for (const body of await getVideosFunctions(server.accessToken)) {
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('normal')
}
})
it('Should be able to see my NSFW videos even with do_not_list user NSFW policy', async function () {
- const res = await getMyVideos(server.url, server.accessToken, 0, 5)
- expect(res.body.total).to.equal(2)
+ const { total, data } = await server.videos.listMyVideos()
+ expect(total).to.equal(2)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
+ expect(data).to.have.lengthOf(2)
+ expect(data[0].name).to.equal('normal')
+ expect(data[1].name).to.equal('nsfw')
})
it('Should display NSFW videos when the nsfw param === true', async function () {
- for (const res of await getVideosFunctions(server.accessToken, { nsfw: true })) {
- expect(res.body.total).to.equal(1)
+ for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'true' })) {
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('nsfw')
}
})
it('Should hide NSFW videos when the nsfw param === true', async function () {
- for (const res of await getVideosFunctions(server.accessToken, { nsfw: false })) {
- expect(res.body.total).to.equal(1)
+ for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'false' })) {
+ expect(body.total).to.equal(1)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('normal')
}
})
it('Should display both videos when the nsfw param === both', async function () {
- for (const res of await getVideosFunctions(server.accessToken, { nsfw: 'both' })) {
- expect(res.body.total).to.equal(2)
+ for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'both' })) {
+ expect(body.total).to.equal(2)
- const videos = res.body.data
+ const videos = body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('normal')
expect(videos[1].name).to.equal('nsfw')
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
- addVideoInPlaylist,
cleanupTests,
- createVideoPlaylist,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getVideoPlaylistsList,
- removeVideoFromPlaylist,
- reorderVideosPlaylist,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
testImage,
- uploadVideoAndGetId,
waitJobs
} from '../../../../shared/extra-utils'
import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
const expect = chai.expect
describe('Playlist thumbnail', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
- let playlistWithoutThumbnail: number
- let playlistWithThumbnail: number
+ let playlistWithoutThumbnailId: number
+ let playlistWithThumbnailId: number
let withThumbnailE1: number
let withThumbnailE2: number
let video1: number
let video2: number
- async function getPlaylistWithoutThumbnail (server: ServerInfo) {
- const res = await getVideoPlaylistsList(server.url, 0, 10)
+ async function getPlaylistWithoutThumbnail (server: PeerTubeServer) {
+ const body = await server.playlists.list({ start: 0, count: 10 })
- return res.body.data.find(p => p.displayName === 'playlist without thumbnail')
+ return body.data.find(p => p.displayName === 'playlist without thumbnail')
}
- async function getPlaylistWithThumbnail (server: ServerInfo) {
- const res = await getVideoPlaylistsList(server.url, 0, 10)
+ async function getPlaylistWithThumbnail (server: PeerTubeServer) {
+ const body = await server.playlists.list({ start: 0, count: 10 })
- return res.body.data.find(p => p.displayName === 'playlist with thumbnail')
+ return body.data.find(p => p.displayName === 'playlist with thumbnail')
}
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: false } })
+ servers = await createMultipleServers(2, { transcoding: { enabled: false } })
// Get the access tokens
await setAccessTokensToServers(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
- video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 1' })).id
- video2 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 2' })).id
+ video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).id
+ video2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).id
await waitJobs(servers)
})
it('Should automatically update the thumbnail when adding an element', async function () {
this.timeout(30000)
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ const created = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist without thumbnail',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
}
})
- playlistWithoutThumbnail = res.body.videoPlaylist.id
+ playlistWithoutThumbnailId = created.id
- const res2 = await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithoutThumbnail,
- elementAttrs: { videoId: video1 }
+ const added = await servers[1].playlists.addElement({
+ playlistId: playlistWithoutThumbnailId,
+ attributes: { videoId: video1 }
})
- withoutThumbnailE1 = res2.body.videoPlaylistElement.id
+ withoutThumbnailE1 = added.id
await waitJobs(servers)
it('Should not update the thumbnail if we explicitly uploaded a thumbnail', async function () {
this.timeout(30000)
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ const created = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist with thumbnail',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].videoChannel.id,
+ videoChannelId: servers[1].store.channel.id,
thumbnailfile: 'thumbnail.jpg'
}
})
- playlistWithThumbnail = res.body.videoPlaylist.id
+ playlistWithThumbnailId = created.id
- const res2 = await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithThumbnail,
- elementAttrs: { videoId: video1 }
+ const added = await servers[1].playlists.addElement({
+ playlistId: playlistWithThumbnailId,
+ attributes: { videoId: video1 }
})
- withThumbnailE1 = res2.body.videoPlaylistElement.id
+ withThumbnailE1 = added.id
await waitJobs(servers)
it('Should automatically update the thumbnail when moving the first element', async function () {
this.timeout(30000)
- const res = await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithoutThumbnail,
- elementAttrs: { videoId: video2 }
+ const added = await servers[1].playlists.addElement({
+ playlistId: playlistWithoutThumbnailId,
+ attributes: { videoId: video2 }
})
- withoutThumbnailE2 = res.body.videoPlaylistElement.id
+ withoutThumbnailE2 = added.id
- await reorderVideosPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithoutThumbnail,
- elementAttrs: {
+ await servers[1].playlists.reorderElements({
+ playlistId: playlistWithoutThumbnailId,
+ attributes: {
startPosition: 1,
insertAfterPosition: 2
}
it('Should not update the thumbnail when moving the first element if we explicitly uploaded a thumbnail', async function () {
this.timeout(30000)
- const res = await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithThumbnail,
- elementAttrs: { videoId: video2 }
+ const added = await servers[1].playlists.addElement({
+ playlistId: playlistWithThumbnailId,
+ attributes: { videoId: video2 }
})
- withThumbnailE2 = res.body.videoPlaylistElement.id
+ withThumbnailE2 = added.id
- await reorderVideosPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithThumbnail,
- elementAttrs: {
+ await servers[1].playlists.reorderElements({
+ playlistId: playlistWithThumbnailId,
+ attributes: {
startPosition: 1,
insertAfterPosition: 2
}
it('Should automatically update the thumbnail when deleting the first element', async function () {
this.timeout(30000)
- await removeVideoFromPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithoutThumbnail,
- playlistElementId: withoutThumbnailE1
+ await servers[1].playlists.removeElement({
+ playlistId: playlistWithoutThumbnailId,
+ elementId: withoutThumbnailE1
})
await waitJobs(servers)
it('Should not update the thumbnail when deleting the first element if we explicitly uploaded a thumbnail', async function () {
this.timeout(30000)
- await removeVideoFromPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithThumbnail,
- playlistElementId: withThumbnailE1
+ await servers[1].playlists.removeElement({
+ playlistId: playlistWithThumbnailId,
+ elementId: withThumbnailE1
})
await waitJobs(servers)
it('Should the thumbnail when we delete the last element', async function () {
this.timeout(30000)
- await removeVideoFromPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithoutThumbnail,
- playlistElementId: withoutThumbnailE2
+ await servers[1].playlists.removeElement({
+ playlistId: playlistWithoutThumbnailId,
+ elementId: withoutThumbnailE2
})
await waitJobs(servers)
it('Should not update the thumbnail when we delete the last element if we explicitly uploaded a thumbnail', async function () {
this.timeout(30000)
- await removeVideoFromPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistId: playlistWithThumbnail,
- playlistElementId: withThumbnailE2
+ await servers[1].playlists.removeElement({
+ playlistId: playlistWithThumbnailId,
+ elementId: withThumbnailE2
})
await waitJobs(servers)
import 'mocha'
import * as chai from 'chai'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoChannel,
- addVideoInPlaylist,
- addVideoToBlacklist,
checkPlaylistFilesWereRemoved,
cleanupTests,
- createUser,
- createVideoPlaylist,
- deleteVideoChannel,
- deleteVideoPlaylist,
+ createMultipleServers,
doubleFollow,
- doVideosExistInMyPlaylist,
- flushAndRunMultipleServers,
- generateUserAccessToken,
- getAccessToken,
- getAccountPlaylistsList,
- getAccountPlaylistsListWithToken,
- getMyUserInformation,
- getPlaylistVideos,
- getVideoChannelPlaylistsList,
- getVideoPlaylist,
- getVideoPlaylistPrivacies,
- getVideoPlaylistsList,
- getVideoPlaylistWithToken,
- removeUser,
- removeVideoFromBlacklist,
- removeVideoFromPlaylist,
- reorderVideosPlaylist,
- ServerInfo,
+ PeerTubeServer,
+ PlaylistsCommand,
setAccessTokensToServers,
setDefaultVideoChannel,
testImage,
- unfollow,
- updateVideo,
- updateVideoPlaylist,
- updateVideoPlaylistElement,
- uploadVideo,
- uploadVideoAndGetId,
- userLogin,
wait,
waitJobs
-} from '../../../../shared/extra-utils'
+} from '@shared/extra-utils'
import {
- addAccountToAccountBlocklist,
- addAccountToServerBlocklist,
- addServerToAccountBlocklist,
- addServerToServerBlocklist,
- removeAccountFromAccountBlocklist,
- removeAccountFromServerBlocklist,
- removeServerFromAccountBlocklist,
- removeServerFromServerBlocklist
-} from '../../../../shared/extra-utils/users/blocklist'
-import { User } from '../../../../shared/models/users'
-import { VideoPlaylistCreateResult, VideoPrivacy } from '../../../../shared/models/videos'
-import { VideoExistInPlaylist } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
-import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../../shared/models/videos/playlist/video-playlist-element.model'
-import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
-import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
-import { VideoPlaylist } from '../../../../shared/models/videos/playlist/video-playlist.model'
+ HttpStatusCode,
+ VideoPlaylist,
+ VideoPlaylistCreateResult,
+ VideoPlaylistElementType,
+ VideoPlaylistPrivacy,
+ VideoPlaylistType,
+ VideoPrivacy
+} from '@shared/models'
const expect = chai.expect
async function checkPlaylistElementType (
- servers: ServerInfo[],
+ servers: PeerTubeServer[],
playlistId: string,
type: VideoPlaylistElementType,
position: number,
total: number
) {
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistId, 0, 10)
- expect(res.body.total).to.equal(total)
+ const body = await server.playlists.listVideos({ token: server.accessToken, playlistId, start: 0, count: 10 })
+ expect(body.total).to.equal(total)
- const videoElement: VideoPlaylistElement = res.body.data.find((e: VideoPlaylistElement) => e.position === position)
+ const videoElement = body.data.find(e => e.position === position)
expect(videoElement.type).to.equal(type, 'On server ' + server.url)
if (type === VideoPlaylistElementType.REGULAR) {
}
describe('Test video playlists', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let playlistServer2Id1: number
let playlistServer2Id2: number
- let playlistServer2UUID2: number
+ let playlistServer2UUID2: string
let playlistServer1Id: number
let playlistServer1UUID: string
let nsfwVideoServer1: number
- let userAccessTokenServer1: string
+ let userTokenServer1: string
+
+ let commands: PlaylistsCommand[]
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(3, { transcoding: { enabled: false } })
+ servers = await createMultipleServers(3, { transcoding: { enabled: false } })
// Get the access tokens
await setAccessTokensToServers(servers)
// Server 1 and server 3 follow each other
await doubleFollow(servers[0], servers[2])
+ commands = servers.map(s => s.playlists)
+
{
- servers[0].videos = []
- servers[1].videos = []
- servers[2].videos = []
+ servers[0].store.videos = []
+ servers[1].store.videos = []
+ servers[2].store.videos = []
for (const server of servers) {
for (let i = 0; i < 7; i++) {
const name = `video ${i} server ${server.serverNumber}`
- const resVideo = await uploadVideo(server.url, server.accessToken, { name, nsfw: false })
+ const video = await server.videos.upload({ attributes: { name, nsfw: false } })
- server.videos.push(resVideo.body.video)
+ server.store.videos.push(video)
}
}
}
- nsfwVideoServer1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'NSFW video', nsfw: true })).id
+ nsfwVideoServer1 = (await servers[0].videos.quickUpload({ name: 'NSFW video', nsfw: true })).id
- {
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: 'user1',
- password: 'password'
- })
- userAccessTokenServer1 = await getAccessToken(servers[0].url, 'user1', 'password')
- }
+ userTokenServer1 = await servers[0].users.generateUserAndToken('user1')
await waitJobs(servers)
})
describe('Get default playlists', function () {
+
it('Should list video playlist privacies', async function () {
- const res = await getVideoPlaylistPrivacies(servers[0].url)
+ const privacies = await commands[0].getPrivacies()
- const privacies = res.body
expect(Object.keys(privacies)).to.have.length.at.least(3)
-
expect(privacies[3]).to.equal('Private')
})
it('Should list watch later playlist', async function () {
- const url = servers[0].url
- const accessToken = servers[0].accessToken
+ const token = servers[0].accessToken
{
- const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
+ const body = await commands[0].listByAccount({ token, handle: 'root', playlistType: VideoPlaylistType.WATCH_LATER })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const playlist: VideoPlaylist = res.body.data[0]
+ const playlist = body.data[0]
expect(playlist.displayName).to.equal('Watch later')
expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER)
expect(playlist.type.label).to.equal('Watch later')
}
{
- const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.REGULAR)
+ const body = await commands[0].listByAccount({ token, handle: 'root', playlistType: VideoPlaylistType.REGULAR })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
{
- const res = await getAccountPlaylistsList(url, 'root', 0, 5)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ const body = await commands[0].listByAccount({ handle: 'root' })
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
}
})
it('Should get private playlist for a classic user', async function () {
- const token = await generateUserAccessToken(servers[0], 'toto')
+ const token = await servers[0].users.generateUserAndToken('toto')
- const res = await getAccountPlaylistsListWithToken(servers[0].url, token, 'toto', 0, 5)
+ const body = await commands[0].listByAccount({ token, handle: 'toto' })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const playlistId = res.body.data[0].id
- await getPlaylistVideos(servers[0].url, token, playlistId, 0, 5)
+ const playlistId = body.data[0].id
+ await commands[0].listVideos({ token, playlistId })
})
})
it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () {
this.timeout(30000)
- await createVideoPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistAttrs: {
+ await commands[0].create({
+ attributes: {
displayName: 'my super playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
description: 'my super description',
thumbnailfile: 'thumbnail.jpg',
- videoChannelId: servers[0].videoChannel.id
+ videoChannelId: servers[0].store.channel.id
}
})
await wait(3000)
for (const server of servers) {
- const res = await getVideoPlaylistsList(server.url, 0, 5)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ const body = await server.playlists.list({ start: 0, count: 5 })
+ expect(body.total).to.equal(1)
+ expect(body.data).to.have.lengthOf(1)
- const playlistFromList = res.body.data[0] as VideoPlaylist
+ const playlistFromList = body.data[0]
- const res2 = await getVideoPlaylist(server.url, playlistFromList.uuid)
- const playlistFromGet = res2.body as VideoPlaylist
+ const playlistFromGet = await server.playlists.get({ playlistId: playlistFromList.uuid })
for (const playlist of [ playlistFromGet, playlistFromList ]) {
expect(playlist.id).to.be.a('number')
this.timeout(30000)
{
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ const playlist = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist 2',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
}
})
- playlistServer2Id1 = res.body.videoPlaylist.id
+ playlistServer2Id1 = playlist.id
}
{
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ const playlist = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist 3',
privacy: VideoPlaylistPrivacy.PUBLIC,
thumbnailfile: 'thumbnail.jpg',
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
}
})
- playlistServer2Id2 = res.body.videoPlaylist.id
- playlistServer2UUID2 = res.body.videoPlaylist.uuid
+ playlistServer2Id2 = playlist.id
+ playlistServer2UUID2 = playlist.uuid
}
for (const id of [ playlistServer2Id1, playlistServer2Id2 ]) {
- await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
+ await servers[1].playlists.addElement({
playlistId: id,
- elementAttrs: { videoId: servers[1].videos[0].id, startTimestamp: 1, stopTimestamp: 2 }
+ attributes: { videoId: servers[1].store.videos[0].id, startTimestamp: 1, stopTimestamp: 2 }
})
- await addVideoInPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
+ await servers[1].playlists.addElement({
playlistId: id,
- elementAttrs: { videoId: servers[1].videos[1].id }
+ attributes: { videoId: servers[1].store.videos[1].id }
})
}
await wait(3000)
for (const server of [ servers[0], servers[1] ]) {
- const res = await getVideoPlaylistsList(server.url, 0, 5)
+ const body = await server.playlists.list({ start: 0, count: 5 })
- const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
+ const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
expect(playlist2).to.not.be.undefined
await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath)
- const playlist3 = res.body.data.find(p => p.displayName === 'playlist 3')
+ const playlist3 = body.data.find(p => p.displayName === 'playlist 3')
expect(playlist3).to.not.be.undefined
await testImage(server.url, 'thumbnail', playlist3.thumbnailPath)
}
- const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
- expect(res.body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
- expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
+ const body = await servers[2].playlists.list({ start: 0, count: 5 })
+ expect(body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
+ expect(body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
})
it('Should have the playlist on server 3 after a new follow', async function () {
// Server 2 and server 3 follow each other
await doubleFollow(servers[1], servers[2])
- const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
+ const body = await servers[2].playlists.list({ start: 0, count: 5 })
- const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
+ const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
expect(playlist2).to.not.be.undefined
await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath)
- expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
+ expect(body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
})
})
this.timeout(30000)
{
- const res = await getVideoPlaylistsList(servers[2].url, 1, 2, 'createdAt')
-
- expect(res.body.total).to.equal(3)
+ const body = await servers[2].playlists.list({ start: 1, count: 2, sort: 'createdAt' })
+ expect(body.total).to.equal(3)
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(2)
expect(data[0].displayName).to.equal('playlist 2')
expect(data[1].displayName).to.equal('playlist 3')
}
{
- const res = await getVideoPlaylistsList(servers[2].url, 1, 2, '-createdAt')
+ const body = await servers[2].playlists.list({ start: 1, count: 2, sort: '-createdAt' })
+ expect(body.total).to.equal(3)
- expect(res.body.total).to.equal(3)
-
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(2)
expect(data[0].displayName).to.equal('playlist 2')
expect(data[1].displayName).to.equal('my super playlist')
this.timeout(30000)
{
- const res = await getVideoChannelPlaylistsList(servers[0].url, 'root_channel', 0, 2, '-createdAt')
-
- expect(res.body.total).to.equal(1)
+ const body = await commands[0].listByChannel({ handle: 'root_channel', start: 0, count: 2, sort: '-createdAt' })
+ expect(body.total).to.equal(1)
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(1)
expect(data[0].displayName).to.equal('my super playlist')
}
this.timeout(30000)
{
- const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, '-createdAt')
+ const body = await servers[1].playlists.listByAccount({ handle: 'root', start: 1, count: 2, sort: '-createdAt' })
+ expect(body.total).to.equal(2)
- expect(res.body.total).to.equal(2)
-
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(1)
expect(data[0].displayName).to.equal('playlist 2')
}
{
- const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, 'createdAt')
-
- expect(res.body.total).to.equal(2)
+ const body = await servers[1].playlists.listByAccount({ handle: 'root', start: 1, count: 2, sort: 'createdAt' })
+ expect(body.total).to.equal(2)
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(1)
expect(data[0].displayName).to.equal('playlist 3')
}
{
- const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '3')
+ const body = await servers[1].playlists.listByAccount({ handle: 'root', sort: 'createdAt', search: '3' })
+ expect(body.total).to.equal(1)
- expect(res.body.total).to.equal(1)
-
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(1)
expect(data[0].displayName).to.equal('playlist 3')
}
{
- const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '4')
-
- expect(res.body.total).to.equal(0)
+ const body = await servers[1].playlists.listByAccount({ handle: 'root', sort: 'createdAt', search: '4' })
+ expect(body.total).to.equal(0)
- const data: VideoPlaylist[] = res.body.data
+ const data = body.data
expect(data).to.have.lengthOf(0)
}
})
this.timeout(30000)
{
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ unlistedPlaylist = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist unlisted',
privacy: VideoPlaylistPrivacy.UNLISTED,
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
}
})
- unlistedPlaylist = res.body.videoPlaylist
}
{
- const res = await createVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ privatePlaylist = await servers[1].playlists.create({
+ attributes: {
displayName: 'playlist private',
privacy: VideoPlaylistPrivacy.PRIVATE
}
})
- privatePlaylist = res.body.videoPlaylist
}
await waitJobs(servers)
it('Should not list unlisted or private playlists', async function () {
for (const server of servers) {
const results = [
- await getAccountPlaylistsList(server.url, 'root@localhost:' + servers[1].port, 0, 5, '-createdAt'),
- await getVideoPlaylistsList(server.url, 0, 2, '-createdAt')
+ await server.playlists.listByAccount({ handle: 'root@localhost:' + servers[1].port, sort: '-createdAt' }),
+ await server.playlists.list({ start: 0, count: 2, sort: '-createdAt' })
]
- expect(results[0].body.total).to.equal(2)
- expect(results[1].body.total).to.equal(3)
+ expect(results[0].total).to.equal(2)
+ expect(results[1].total).to.equal(3)
- for (const res of results) {
- const data: VideoPlaylist[] = res.body.data
+ for (const body of results) {
+ const data = body.data
expect(data).to.have.lengthOf(2)
expect(data[0].displayName).to.equal('playlist 3')
expect(data[1].displayName).to.equal('playlist 2')
})
it('Should not get unlisted playlist using only the id', async function () {
- await getVideoPlaylist(servers[1].url, unlistedPlaylist.id, 404)
+ await servers[1].playlists.get({ playlistId: unlistedPlaylist.id, expectedStatus: 404 })
})
it('Should get unlisted plyaylist using uuid or shortUUID', async function () {
- await getVideoPlaylist(servers[1].url, unlistedPlaylist.uuid)
- await getVideoPlaylist(servers[1].url, unlistedPlaylist.shortUUID)
+ await servers[1].playlists.get({ playlistId: unlistedPlaylist.uuid })
+ await servers[1].playlists.get({ playlistId: unlistedPlaylist.shortUUID })
})
it('Should not get private playlist without token', async function () {
for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
- await getVideoPlaylist(servers[1].url, id, 401)
+ await servers[1].playlists.get({ playlistId: id, expectedStatus: 401 })
}
})
it('Should get private playlist with a token', async function () {
for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
- await getVideoPlaylistWithToken(servers[1].url, servers[1].accessToken, id)
+ await servers[1].playlists.get({ token: servers[1].accessToken, playlistId: id })
}
})
})
it('Should update a playlist', async function () {
this.timeout(30000)
- await updateVideoPlaylist({
- url: servers[1].url,
- token: servers[1].accessToken,
- playlistAttrs: {
+ await servers[1].playlists.update({
+ attributes: {
displayName: 'playlist 3 updated',
description: 'description updated',
privacy: VideoPlaylistPrivacy.UNLISTED,
thumbnailfile: 'thumbnail.jpg',
- videoChannelId: servers[1].videoChannel.id
+ videoChannelId: servers[1].store.channel.id
},
playlistId: playlistServer2Id2
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideoPlaylist(server.url, playlistServer2UUID2)
- const playlist: VideoPlaylist = res.body
+ const playlist = await server.playlists.get({ playlistId: playlistServer2UUID2 })
expect(playlist.displayName).to.equal('playlist 3 updated')
expect(playlist.description).to.equal('description updated')
it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () {
this.timeout(30000)
- const addVideo = (elementAttrs: any) => {
- return addVideoInPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: playlistServer1Id, elementAttrs })
+ const addVideo = (attributes: any) => {
+ return commands[0].addElement({ playlistId: playlistServer1Id, attributes })
}
- const res = await createVideoPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistAttrs: {
+ const playlist = await commands[0].create({
+ attributes: {
displayName: 'playlist 4',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].videoChannel.id
+ videoChannelId: servers[0].store.channel.id
}
})
- playlistServer1Id = res.body.videoPlaylist.id
- playlistServer1UUID = res.body.videoPlaylist.uuid
+ playlistServer1Id = playlist.id
+ playlistServer1UUID = playlist.uuid
- await addVideo({ videoId: servers[0].videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
- await addVideo({ videoId: servers[2].videos[1].uuid, startTimestamp: 35 })
- await addVideo({ videoId: servers[2].videos[2].uuid })
+ await addVideo({ videoId: servers[0].store.videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
+ await addVideo({ videoId: servers[2].store.videos[1].uuid, startTimestamp: 35 })
+ await addVideo({ videoId: servers[2].store.videos[2].uuid })
{
- const res = await addVideo({ videoId: servers[0].videos[3].uuid, stopTimestamp: 35 })
- playlistElementServer1Video4 = res.body.videoPlaylistElement.id
+ const element = await addVideo({ videoId: servers[0].store.videos[3].uuid, stopTimestamp: 35 })
+ playlistElementServer1Video4 = element.id
}
{
- const res = await addVideo({ videoId: servers[0].videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
- playlistElementServer1Video5 = res.body.videoPlaylistElement.id
+ const element = await addVideo({ videoId: servers[0].store.videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
+ playlistElementServer1Video5 = element.id
}
{
- const res = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
- playlistElementNSFW = res.body.videoPlaylistElement.id
+ const element = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
+ playlistElementNSFW = element.id
await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 })
await addVideo({ videoId: nsfwVideoServer1 })
this.timeout(30000)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
-
- expect(res.body.total).to.equal(8)
-
- const videoElements: VideoPlaylistElement[] = res.body.data
- expect(videoElements).to.have.lengthOf(8)
-
- expect(videoElements[0].video.name).to.equal('video 0 server 1')
- expect(videoElements[0].position).to.equal(1)
- expect(videoElements[0].startTimestamp).to.equal(15)
- expect(videoElements[0].stopTimestamp).to.equal(28)
-
- expect(videoElements[1].video.name).to.equal('video 1 server 3')
- expect(videoElements[1].position).to.equal(2)
- expect(videoElements[1].startTimestamp).to.equal(35)
- expect(videoElements[1].stopTimestamp).to.be.null
-
- expect(videoElements[2].video.name).to.equal('video 2 server 3')
- expect(videoElements[2].position).to.equal(3)
- expect(videoElements[2].startTimestamp).to.be.null
- expect(videoElements[2].stopTimestamp).to.be.null
-
- expect(videoElements[3].video.name).to.equal('video 3 server 1')
- expect(videoElements[3].position).to.equal(4)
- expect(videoElements[3].startTimestamp).to.be.null
- expect(videoElements[3].stopTimestamp).to.equal(35)
-
- expect(videoElements[4].video.name).to.equal('video 4 server 1')
- expect(videoElements[4].position).to.equal(5)
- expect(videoElements[4].startTimestamp).to.equal(45)
- expect(videoElements[4].stopTimestamp).to.equal(60)
-
- expect(videoElements[5].video.name).to.equal('NSFW video')
- expect(videoElements[5].position).to.equal(6)
- expect(videoElements[5].startTimestamp).to.equal(5)
- expect(videoElements[5].stopTimestamp).to.be.null
-
- expect(videoElements[6].video.name).to.equal('NSFW video')
- expect(videoElements[6].position).to.equal(7)
- expect(videoElements[6].startTimestamp).to.equal(4)
- expect(videoElements[6].stopTimestamp).to.be.null
-
- expect(videoElements[7].video.name).to.equal('NSFW video')
- expect(videoElements[7].position).to.equal(8)
- expect(videoElements[7].startTimestamp).to.be.null
- expect(videoElements[7].stopTimestamp).to.be.null
-
- const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2)
- expect(res3.body.data).to.have.lengthOf(2)
+ {
+ const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
+
+ expect(body.total).to.equal(8)
+
+ const videoElements = body.data
+ expect(videoElements).to.have.lengthOf(8)
+
+ expect(videoElements[0].video.name).to.equal('video 0 server 1')
+ expect(videoElements[0].position).to.equal(1)
+ expect(videoElements[0].startTimestamp).to.equal(15)
+ expect(videoElements[0].stopTimestamp).to.equal(28)
+
+ expect(videoElements[1].video.name).to.equal('video 1 server 3')
+ expect(videoElements[1].position).to.equal(2)
+ expect(videoElements[1].startTimestamp).to.equal(35)
+ expect(videoElements[1].stopTimestamp).to.be.null
+
+ expect(videoElements[2].video.name).to.equal('video 2 server 3')
+ expect(videoElements[2].position).to.equal(3)
+ expect(videoElements[2].startTimestamp).to.be.null
+ expect(videoElements[2].stopTimestamp).to.be.null
+
+ expect(videoElements[3].video.name).to.equal('video 3 server 1')
+ expect(videoElements[3].position).to.equal(4)
+ expect(videoElements[3].startTimestamp).to.be.null
+ expect(videoElements[3].stopTimestamp).to.equal(35)
+
+ expect(videoElements[4].video.name).to.equal('video 4 server 1')
+ expect(videoElements[4].position).to.equal(5)
+ expect(videoElements[4].startTimestamp).to.equal(45)
+ expect(videoElements[4].stopTimestamp).to.equal(60)
+
+ expect(videoElements[5].video.name).to.equal('NSFW video')
+ expect(videoElements[5].position).to.equal(6)
+ expect(videoElements[5].startTimestamp).to.equal(5)
+ expect(videoElements[5].stopTimestamp).to.be.null
+
+ expect(videoElements[6].video.name).to.equal('NSFW video')
+ expect(videoElements[6].position).to.equal(7)
+ expect(videoElements[6].startTimestamp).to.equal(4)
+ expect(videoElements[6].stopTimestamp).to.be.null
+
+ expect(videoElements[7].video.name).to.equal('NSFW video')
+ expect(videoElements[7].position).to.equal(8)
+ expect(videoElements[7].startTimestamp).to.be.null
+ expect(videoElements[7].stopTimestamp).to.be.null
+ }
+
+ {
+ const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 2 })
+ expect(body.data).to.have.lengthOf(2)
+ }
}
})
})
describe('Element type', function () {
- let groupUser1: ServerInfo[]
- let groupWithoutToken1: ServerInfo[]
- let group1: ServerInfo[]
- let group2: ServerInfo[]
+ let groupUser1: PeerTubeServer[]
+ let groupWithoutToken1: PeerTubeServer[]
+ let group1: PeerTubeServer[]
+ let group2: PeerTubeServer[]
let video1: string
let video2: string
before(async function () {
this.timeout(60000)
- groupUser1 = [ Object.assign({}, servers[0], { accessToken: userAccessTokenServer1 }) ]
+ groupUser1 = [ Object.assign({}, servers[0], { accessToken: userTokenServer1 }) ]
groupWithoutToken1 = [ Object.assign({}, servers[0], { accessToken: undefined }) ]
group1 = [ servers[0] ]
group2 = [ servers[1], servers[2] ]
- const res = await createVideoPlaylist({
- url: servers[0].url,
- token: userAccessTokenServer1,
- playlistAttrs: {
+ const playlist = await commands[0].create({
+ token: userTokenServer1,
+ attributes: {
displayName: 'playlist 56',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].videoChannel.id
+ videoChannelId: servers[0].store.channel.id
}
})
- const playlistServer1Id2 = res.body.videoPlaylist.id
- playlistServer1UUID2 = res.body.videoPlaylist.uuid
+ const playlistServer1Id2 = playlist.id
+ playlistServer1UUID2 = playlist.uuid
- const addVideo = (elementAttrs: any) => {
- return addVideoInPlaylist({ url: servers[0].url, token: userAccessTokenServer1, playlistId: playlistServer1Id2, elementAttrs })
+ const addVideo = (attributes: any) => {
+ return commands[0].addElement({ token: userTokenServer1, playlistId: playlistServer1Id2, attributes })
}
- video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 89', token: userAccessTokenServer1 })).uuid
- video2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 90' })).uuid
- video3 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 91', nsfw: true })).uuid
+ video1 = (await servers[0].videos.quickUpload({ name: 'video 89', token: userTokenServer1 })).uuid
+ video2 = (await servers[1].videos.quickUpload({ name: 'video 90' })).uuid
+ video3 = (await servers[0].videos.quickUpload({ name: 'video 91', nsfw: true })).uuid
await waitJobs(servers)
const position = 1
{
- await updateVideo(servers[0].url, servers[0].accessToken, video1, { privacy: VideoPrivacy.PRIVATE })
+ await servers[0].videos.update({ id: video1, attributes: { privacy: VideoPrivacy.PRIVATE } })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
}
{
- await updateVideo(servers[0].url, servers[0].accessToken, video1, { privacy: VideoPrivacy.PUBLIC })
+ await servers[0].videos.update({ id: video1, attributes: { privacy: VideoPrivacy.PUBLIC } })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
const position = 1
{
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, video1, 'reason', true)
+ await servers[0].blacklist.add({ videoId: video1, reason: 'reason', unfederate: true })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
}
{
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, video1)
+ await servers[0].blacklist.remove({ videoId: video1 })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
it('Should update the element type if the account or server of the video is blocked', async function () {
this.timeout(90000)
+ const command = servers[0].blocklist
+
const name = 'video 90'
const position = 2
{
- await addAccountToAccountBlocklist(servers[0].url, userAccessTokenServer1, 'root@localhost:' + servers[1].port)
+ await command.addToMyBlocklist({ token: userTokenServer1, account: 'root@localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await removeAccountFromAccountBlocklist(servers[0].url, userAccessTokenServer1, 'root@localhost:' + servers[1].port)
+ await command.removeFromMyBlocklist({ token: userTokenServer1, account: 'root@localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
}
{
- await addServerToAccountBlocklist(servers[0].url, userAccessTokenServer1, 'localhost:' + servers[1].port)
+ await command.addToMyBlocklist({ token: userTokenServer1, server: 'localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await removeServerFromAccountBlocklist(servers[0].url, userAccessTokenServer1, 'localhost:' + servers[1].port)
+ await command.removeFromMyBlocklist({ token: userTokenServer1, server: 'localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
}
{
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'root@localhost:' + servers[1].port)
+ await command.addToServerBlocklist({ account: 'root@localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'root@localhost:' + servers[1].port)
+ await command.removeFromServerBlocklist({ account: 'root@localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
}
{
- await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.addToServerBlocklist({ server: 'localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await command.removeFromServerBlocklist({ server: 'localhost:' + servers[1].port })
await waitJobs(servers)
await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
})
it('Should hide the video if it is NSFW', async function () {
- const res = await getPlaylistVideos(servers[0].url, userAccessTokenServer1, playlistServer1UUID2, 0, 10, { nsfw: false })
- expect(res.body.total).to.equal(3)
+ const body = await commands[0].listVideos({ token: userTokenServer1, playlistId: playlistServer1UUID2, query: { nsfw: 'false' } })
+ expect(body.total).to.equal(3)
- const elements: VideoPlaylistElement[] = res.body.data
+ const elements = body.data
const element = elements.find(e => e.position === 3)
expect(element).to.exist
this.timeout(30000)
{
- await reorderVideosPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await commands[0].reorderElements({
playlistId: playlistServer1Id,
- elementAttrs: {
+ attributes: {
startPosition: 2,
insertAfterPosition: 3
}
await waitJobs(servers)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
- const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name)
+ const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
+ const names = body.data.map(v => v.video.name)
expect(names).to.deep.equal([
'video 0 server 1',
}
{
- await reorderVideosPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await commands[0].reorderElements({
playlistId: playlistServer1Id,
- elementAttrs: {
+ attributes: {
startPosition: 1,
reorderLength: 3,
insertAfterPosition: 4
await waitJobs(servers)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
- const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name)
+ const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
+ const names = body.data.map(v => v.video.name)
expect(names).to.deep.equal([
'video 3 server 1',
}
{
- await reorderVideosPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await commands[0].reorderElements({
playlistId: playlistServer1Id,
- elementAttrs: {
+ attributes: {
startPosition: 6,
insertAfterPosition: 3
}
await waitJobs(servers)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
- const elements: VideoPlaylistElement[] = res.body.data
+ const { data: elements } = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
const names = elements.map(v => v.video.name)
expect(names).to.deep.equal([
it('Should update startTimestamp/endTimestamp of some elements', async function () {
this.timeout(30000)
- await updateVideoPlaylistElement({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await commands[0].updateElement({
playlistId: playlistServer1Id,
- playlistElementId: playlistElementServer1Video4,
- elementAttrs: {
+ elementId: playlistElementServer1Video4,
+ attributes: {
startTimestamp: 1
}
})
- await updateVideoPlaylistElement({
- url: servers[0].url,
- token: servers[0].accessToken,
+ await commands[0].updateElement({
playlistId: playlistServer1Id,
- playlistElementId: playlistElementServer1Video5,
- elementAttrs: {
+ elementId: playlistElementServer1Video5,
+ attributes: {
stopTimestamp: null
}
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
- const elements: VideoPlaylistElement[] = res.body.data
+ const { data: elements } = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
expect(elements[0].video.name).to.equal('video 3 server 1')
expect(elements[0].position).to.equal(1)
it('Should check videos existence in my playlist', async function () {
const videoIds = [
- servers[0].videos[0].id,
+ servers[0].store.videos[0].id,
42000,
- servers[0].videos[3].id,
+ servers[0].store.videos[3].id,
43000,
- servers[0].videos[4].id
+ servers[0].store.videos[4].id
]
- const res = await doVideosExistInMyPlaylist(servers[0].url, servers[0].accessToken, videoIds)
- const obj = res.body as VideoExistInPlaylist
+ const obj = await commands[0].videosExist({ videoIds })
{
- const elem = obj[servers[0].videos[0].id]
+ const elem = obj[servers[0].store.videos[0].id]
expect(elem).to.have.lengthOf(1)
expect(elem[0].playlistElementId).to.exist
expect(elem[0].playlistId).to.equal(playlistServer1Id)
}
{
- const elem = obj[servers[0].videos[3].id]
+ const elem = obj[servers[0].store.videos[3].id]
expect(elem).to.have.lengthOf(1)
expect(elem[0].playlistElementId).to.equal(playlistElementServer1Video4)
expect(elem[0].playlistId).to.equal(playlistServer1Id)
}
{
- const elem = obj[servers[0].videos[4].id]
+ const elem = obj[servers[0].store.videos[4].id]
expect(elem).to.have.lengthOf(1)
expect(elem[0].playlistId).to.equal(playlistServer1Id)
expect(elem[0].startTimestamp).to.equal(45)
it('Should automatically update updatedAt field of playlists', async function () {
const server = servers[1]
- const videoId = servers[1].videos[5].id
+ const videoId = servers[1].store.videos[5].id
async function getPlaylistNames () {
- const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, undefined, '-updatedAt')
+ const { data } = await server.playlists.listByAccount({ token: server.accessToken, handle: 'root', sort: '-updatedAt' })
- return (res.body.data as VideoPlaylist[]).map(p => p.displayName)
+ return data.map(p => p.displayName)
}
- const elementAttrs = { videoId }
- const res1 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id1, elementAttrs })
- const res2 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id2, elementAttrs })
-
- const element1 = res1.body.videoPlaylistElement.id
- const element2 = res2.body.videoPlaylistElement.id
+ const attributes = { videoId }
+ const element1 = await server.playlists.addElement({ playlistId: playlistServer2Id1, attributes })
+ const element2 = await server.playlists.addElement({ playlistId: playlistServer2Id2, attributes })
const names1 = await getPlaylistNames()
expect(names1[0]).to.equal('playlist 3 updated')
expect(names1[1]).to.equal('playlist 2')
- await removeVideoFromPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: playlistServer2Id1,
- playlistElementId: element1
- })
+ await server.playlists.removeElement({ playlistId: playlistServer2Id1, elementId: element1.id })
const names2 = await getPlaylistNames()
expect(names2[0]).to.equal('playlist 2')
expect(names2[1]).to.equal('playlist 3 updated')
- await removeVideoFromPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistId: playlistServer2Id2,
- playlistElementId: element2
- })
+ await server.playlists.removeElement({ playlistId: playlistServer2Id2, elementId: element2.id })
const names3 = await getPlaylistNames()
expect(names3[0]).to.equal('playlist 3 updated')
it('Should delete some elements', async function () {
this.timeout(30000)
- await removeVideoFromPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistId: playlistServer1Id,
- playlistElementId: playlistElementServer1Video4
- })
-
- await removeVideoFromPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistId: playlistServer1Id,
- playlistElementId: playlistElementNSFW
- })
+ await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementServer1Video4 })
+ await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementNSFW })
await waitJobs(servers)
for (const server of servers) {
- const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
+ const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
+ expect(body.total).to.equal(6)
- expect(res.body.total).to.equal(6)
-
- const elements: VideoPlaylistElement[] = res.body.data
+ const elements = body.data
expect(elements).to.have.lengthOf(6)
expect(elements[0].video.name).to.equal('video 0 server 1')
it('Should be able to create a public playlist, and set it to private', async function () {
this.timeout(30000)
- const res = await createVideoPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistAttrs: {
+ const videoPlaylistIds = await commands[0].create({
+ attributes: {
displayName: 'my super public playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].videoChannel.id
+ videoChannelId: servers[0].store.channel.id
}
})
- const videoPlaylistIds = res.body.videoPlaylist
await waitJobs(servers)
for (const server of servers) {
- await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
+ await server.playlists.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
}
- const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
- await updateVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: videoPlaylistIds.id, playlistAttrs })
+ const attributes = { privacy: VideoPlaylistPrivacy.PRIVATE }
+ await commands[0].update({ playlistId: videoPlaylistIds.id, attributes })
await waitJobs(servers)
for (const server of [ servers[1], servers[2] ]) {
- await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404)
+ await server.playlists.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
- await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
- await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
+ await commands[0].get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await commands[0].get({ token: servers[0].accessToken, playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
})
})
it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () {
this.timeout(30000)
- await deleteVideoPlaylist(servers[0].url, servers[0].accessToken, playlistServer1Id)
+ await commands[0].delete({ playlistId: playlistServer1Id })
await waitJobs(servers)
for (const server of servers) {
- await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404)
+ await server.playlists.get({ playlistId: playlistServer1UUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
})
it('Should unfollow servers 1 and 2 and hide their playlists', async function () {
this.timeout(30000)
- const finder = data => data.find(p => p.displayName === 'my super playlist')
+ const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'my super playlist')
{
- const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
- expect(res.body.total).to.equal(3)
- expect(finder(res.body.data)).to.not.be.undefined
+ const body = await servers[2].playlists.list({ start: 0, count: 5 })
+ expect(body.total).to.equal(3)
+
+ expect(finder(body.data)).to.not.be.undefined
}
- await unfollow(servers[2].url, servers[2].accessToken, servers[0])
+ await servers[2].follows.unfollow({ target: servers[0] })
{
- const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
- expect(res.body.total).to.equal(1)
+ const body = await servers[2].playlists.list({ start: 0, count: 5 })
+ expect(body.total).to.equal(1)
- expect(finder(res.body.data)).to.be.undefined
+ expect(finder(body.data)).to.be.undefined
}
})
it('Should delete a channel and put the associated playlist in private mode', async function () {
this.timeout(30000)
- const res = await addVideoChannel(servers[0].url, servers[0].accessToken, { name: 'super_channel', displayName: 'super channel' })
- const videoChannelId = res.body.videoChannel.id
+ const channel = await servers[0].channels.create({ attributes: { name: 'super_channel', displayName: 'super channel' } })
- const res2 = await createVideoPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistAttrs: {
+ const playlistCreated = await commands[0].create({
+ attributes: {
displayName: 'channel playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId
+ videoChannelId: channel.id
}
})
- const videoPlaylistUUID = res2.body.videoPlaylist.uuid
await waitJobs(servers)
- await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'super_channel')
+ await servers[0].channels.delete({ channelName: 'super_channel' })
await waitJobs(servers)
- const res3 = await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistUUID)
- expect(res3.body.displayName).to.equal('channel playlist')
- expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
+ const body = await commands[0].get({ token: servers[0].accessToken, playlistId: playlistCreated.uuid })
+ expect(body.displayName).to.equal('channel playlist')
+ expect(body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
- await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404)
+ await servers[1].playlists.get({ playlistId: playlistCreated.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should delete an account and delete its playlists', async function () {
this.timeout(30000)
- const user = { username: 'user_1', password: 'password' }
- const res = await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: user.username,
- password: user.password
- })
-
- const userId = res.body.user.id
- const userAccessToken = await userLogin(servers[0], user)
+ const { userId, token } = await servers[0].users.generate('user_1')
- const resChannel = await getMyUserInformation(servers[0].url, userAccessToken)
- const userChannel = (resChannel.body as User).videoChannels[0]
+ const { videoChannels } = await servers[0].users.getMyInfo({ token })
+ const userChannel = videoChannels[0]
- await createVideoPlaylist({
- url: servers[0].url,
- token: userAccessToken,
- playlistAttrs: {
+ await commands[0].create({
+ attributes: {
displayName: 'playlist to be deleted',
privacy: VideoPlaylistPrivacy.PUBLIC,
videoChannelId: userChannel.id
await waitJobs(servers)
- const finder = data => data.find(p => p.displayName === 'playlist to be deleted')
+ const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'playlist to be deleted')
{
for (const server of [ servers[0], servers[1] ]) {
- const res = await getVideoPlaylistsList(server.url, 0, 15)
- expect(finder(res.body.data)).to.not.be.undefined
+ const body = await server.playlists.list({ start: 0, count: 15 })
+
+ expect(finder(body.data)).to.not.be.undefined
}
}
- await removeUser(servers[0].url, userId, servers[0].accessToken)
+ await servers[0].users.remove({ userId })
await waitJobs(servers)
{
for (const server of [ servers[0], servers[1] ]) {
- const res = await getVideoPlaylistsList(server.url, 0, 15)
- expect(finder(res.body.data)).to.be.undefined
+ const body = await server.playlists.list({ start: 0, count: 15 })
+
+ expect(finder(body.data)).to.be.undefined
}
}
})
import 'mocha'
import * as chai from 'chai'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { Video, VideoCreateResult } from '@shared/models'
-import {
- cleanupTests,
- flushAndRunServer,
- getVideosList,
- getVideosListWithToken,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '../../../../shared/extra-utils/index'
-import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
-import { userLogin } from '../../../../shared/extra-utils/users/login'
-import { createUser } from '../../../../shared/extra-utils/users/users'
-import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos'
-import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
+import { cleanupTests, createSingleServer, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test video privacy', function () {
- const servers: ServerInfo[] = []
+ const servers: PeerTubeServer[] = []
let anotherUserToken: string
let privateVideoId: number
this.timeout(50000)
// Run servers
- servers.push(await flushAndRunServer(1, dontFederateUnlistedConfig))
- servers.push(await flushAndRunServer(2))
+ servers.push(await createSingleServer(1, dontFederateUnlistedConfig))
+ servers.push(await createSingleServer(2))
// Get the access tokens
await setAccessTokensToServers(servers)
for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) {
const attributes = { privacy }
- await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
+ await servers[0].videos.upload({ attributes })
}
await waitJobs(servers)
})
it('Should not have these private and internal videos on server 2', async function () {
- const res = await getVideosList(servers[1].url)
+ const { total, data } = await servers[1].videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
})
it('Should not list the private and internal videos for an unauthenticated user on server 1', async function () {
- const res = await getVideosList(servers[0].url)
+ const { total, data } = await servers[0].videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
})
it('Should not list the private video and list the internal video for an authenticated user on server 1', async function () {
- const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
+ const { total, data } = await servers[0].videos.listWithToken()
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
- expect(res.body.data[0].privacy.id).to.equal(VideoPrivacy.INTERNAL)
+ expect(data[0].privacy.id).to.equal(VideoPrivacy.INTERNAL)
})
it('Should list my (private and internal) videos', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 10)
+ const { total, data } = await servers[0].videos.listMyVideos()
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ expect(total).to.equal(2)
+ expect(data).to.have.lengthOf(2)
- const videos: Video[] = res.body.data
-
- const privateVideo = videos.find(v => v.privacy.id === VideoPrivacy.PRIVATE)
+ const privateVideo = data.find(v => v.privacy.id === VideoPrivacy.PRIVATE)
privateVideoId = privateVideo.id
privateVideoUUID = privateVideo.uuid
- const internalVideo = videos.find(v => v.privacy.id === VideoPrivacy.INTERNAL)
+ const internalVideo = data.find(v => v.privacy.id === VideoPrivacy.INTERNAL)
internalVideoId = internalVideo.id
internalVideoUUID = internalVideo.uuid
})
it('Should not be able to watch the private/internal video with non authenticated user', async function () {
- await getVideo(servers[0].url, privateVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
- await getVideo(servers[0].url, internalVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
+ await servers[0].videos.get({ id: privateVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
+ await servers[0].videos.get({ id: internalVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should not be able to watch the private video with another user', async function () {
username: 'hello',
password: 'super password'
}
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
+ await servers[0].users.create({ username: user.username, password: user.password })
+
+ anotherUserToken = await servers[0].login.getAccessToken(user)
- anotherUserToken = await userLogin(servers[0], user)
- await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].videos.getWithToken({
+ token: anotherUserToken,
+ id: privateVideoUUID,
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should be able to watch the internal video with another user', async function () {
- await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ token: anotherUserToken, id: internalVideoUUID })
})
it('Should be able to watch the private video with the correct user', async function () {
- await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, HttpStatusCode.OK_200)
+ await servers[0].videos.getWithToken({ id: privateVideoUUID })
})
})
name: 'unlisted video',
privacy: VideoPrivacy.UNLISTED
}
- await uploadVideo(servers[1].url, servers[1].accessToken, attributes)
+ await servers[1].videos.upload({ attributes })
// Server 2 has transcoding enabled
await waitJobs(servers)
it('Should not have this unlisted video listed on server 1 and 2', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
}
})
it('Should list my (unlisted) videos', async function () {
- const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 1)
+ const { total, data } = await servers[1].videos.listMyVideos()
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.have.lengthOf(1)
+ expect(total).to.equal(1)
+ expect(data).to.have.lengthOf(1)
- unlistedVideo = res.body.data[0]
+ unlistedVideo = data[0]
})
it('Should not be able to get this unlisted video using its id', async function () {
- await getVideo(servers[1].url, unlistedVideo.id, 404)
+ await servers[1].videos.get({ id: unlistedVideo.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
it('Should be able to get this unlisted video using its uuid/shortUUID', async function () {
for (const server of servers) {
for (const id of [ unlistedVideo.uuid, unlistedVideo.shortUUID ]) {
- const res = await getVideo(server.url, id)
+ const video = await server.videos.get({ id })
- expect(res.body.name).to.equal('unlisted video')
+ expect(video.name).to.equal('unlisted video')
}
}
})
name: 'unlisted video',
privacy: VideoPrivacy.UNLISTED
}
- await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
+ await servers[0].videos.upload({ attributes })
await waitJobs(servers)
})
it('Should list my new unlisted video', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 3)
+ const { total, data } = await servers[0].videos.listMyVideos()
- expect(res.body.total).to.equal(3)
- expect(res.body.data).to.have.lengthOf(3)
+ expect(total).to.equal(3)
+ expect(data).to.have.lengthOf(3)
- nonFederatedUnlistedVideoUUID = res.body.data[0].uuid
+ nonFederatedUnlistedVideoUUID = data[0].uuid
})
it('Should be able to get non-federated unlisted video from origin', async function () {
- const res = await getVideo(servers[0].url, nonFederatedUnlistedVideoUUID)
+ const video = await servers[0].videos.get({ id: nonFederatedUnlistedVideoUUID })
- expect(res.body.name).to.equal('unlisted video')
+ expect(video.name).to.equal('unlisted video')
})
it('Should not be able to get non-federated unlisted video from federated server', async function () {
- await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, HttpStatusCode.NOT_FOUND_404)
+ await servers[1].videos.get({ id: nonFederatedUnlistedVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
})
})
now = Date.now()
{
- const attribute = {
+ const attributes = {
name: 'private video becomes public',
privacy: VideoPrivacy.PUBLIC
}
- await updateVideo(servers[0].url, servers[0].accessToken, privateVideoId, attribute)
+ await servers[0].videos.update({ id: privateVideoId, attributes })
}
{
- const attribute = {
+ const attributes = {
name: 'internal video becomes public',
privacy: VideoPrivacy.PUBLIC
}
- await updateVideo(servers[0].url, servers[0].accessToken, internalVideoId, attribute)
+ await servers[0].videos.update({ id: internalVideoId, attributes })
}
await waitJobs(servers)
it('Should have this new public video listed on server 1 and 2', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(2)
+ expect(data).to.have.lengthOf(2)
- const videos: Video[] = res.body.data
- const privateVideo = videos.find(v => v.name === 'private video becomes public')
- const internalVideo = videos.find(v => v.name === 'internal video becomes public')
+ const privateVideo = data.find(v => v.name === 'private video becomes public')
+ const internalVideo = data.find(v => v.name === 'internal video becomes public')
expect(privateVideo).to.not.be.undefined
expect(internalVideo).to.not.be.undefined
it('Should set these videos as private and internal', async function () {
this.timeout(10000)
- await updateVideo(servers[0].url, servers[0].accessToken, internalVideoId, { privacy: VideoPrivacy.PRIVATE })
- await updateVideo(servers[0].url, servers[0].accessToken, privateVideoId, { privacy: VideoPrivacy.INTERNAL })
+ await servers[0].videos.update({ id: internalVideoId, attributes: { privacy: VideoPrivacy.PRIVATE } })
+ await servers[0].videos.update({ id: privateVideoId, attributes: { privacy: VideoPrivacy.INTERNAL } })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(total).to.equal(0)
+ expect(data).to.have.lengthOf(0)
}
{
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
- const videos = res.body.data
-
- expect(res.body.total).to.equal(3)
- expect(videos).to.have.lengthOf(3)
+ const { total, data } = await servers[0].videos.listMyVideos()
+ expect(total).to.equal(3)
+ expect(data).to.have.lengthOf(3)
- const privateVideo = videos.find(v => v.name === 'private video becomes public')
- const internalVideo = videos.find(v => v.name === 'internal video becomes public')
+ const privateVideo = data.find(v => v.name === 'private video becomes public')
+ const internalVideo = data.find(v => v.name === 'internal video becomes public')
expect(privateVideo).to.not.be.undefined
expect(internalVideo).to.not.be.undefined
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { VideoPrivacy } from '../../../../shared/models/videos'
+import * as chai from 'chai'
import {
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getMyVideos,
- getVideosList,
- getVideoWithToken,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateVideo,
- uploadVideo,
- wait
-} from '../../../../shared/extra-utils'
-import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPrivacy } from '@shared/models'
const expect = chai.expect
}
describe('Test video update scheduler', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let video2UUID: string
before(async function () {
this.timeout(30000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
it('Should upload a video and schedule an update in 10 seconds', async function () {
this.timeout(10000)
- const videoAttributes = {
+ const attributes = {
name: 'video 1',
privacy: VideoPrivacy.PRIVATE,
scheduleUpdate: {
updateAt: in10Seconds().toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ await servers[0].videos.upload({ attributes })
await waitJobs(servers)
})
it('Should not list the video (in privacy mode)', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total } = await server.videos.list()
- expect(res.body.total).to.equal(0)
+ expect(total).to.equal(0)
}
})
it('Should have my scheduled video in my account videos', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
- expect(res.body.total).to.equal(1)
+ const { total, data } = await servers[0].videos.listMyVideos()
+ expect(total).to.equal(1)
- const videoFromList = res.body.data[0]
- const res2 = await getVideoWithToken(servers[0].url, servers[0].accessToken, videoFromList.uuid)
- const videoFromGet = res2.body
+ const videoFromList = data[0]
+ const videoFromGet = await servers[0].videos.getWithToken({ id: videoFromList.uuid })
for (const video of [ videoFromList, videoFromGet ]) {
expect(video.name).to.equal('video 1')
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total, data } = await server.videos.list()
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('video 1')
+ expect(total).to.equal(1)
+ expect(data[0].name).to.equal('video 1')
}
})
it('Should upload a video without scheduling an update', async function () {
this.timeout(10000)
- const videoAttributes = {
+ const attributes = {
name: 'video 2',
privacy: VideoPrivacy.PRIVATE
}
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- video2UUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes })
+ video2UUID = uuid
await waitJobs(servers)
})
it('Should update a video by scheduling an update', async function () {
this.timeout(10000)
- const videoAttributes = {
+ const attributes = {
name: 'video 2 updated',
scheduleUpdate: {
updateAt: in10Seconds().toISOString(),
- privacy: VideoPrivacy.PUBLIC
+ privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
}
}
- await updateVideo(servers[0].url, servers[0].accessToken, video2UUID, videoAttributes)
+ await servers[0].videos.update({ id: video2UUID, attributes })
await waitJobs(servers)
})
it('Should not display the updated video', async function () {
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { total } = await server.videos.list()
- expect(res.body.total).to.equal(1)
+ expect(total).to.equal(1)
}
})
it('Should have my scheduled updated video in my account videos', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
- expect(res.body.total).to.equal(2)
+ const { total, data } = await servers[0].videos.listMyVideos()
+ expect(total).to.equal(2)
- const video = res.body.data.find(v => v.uuid === video2UUID)
+ const video = data.find(v => v.uuid === video2UUID)
expect(video).not.to.be.undefined
expect(video.name).to.equal('video 2 updated')
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
-
- expect(res.body.total).to.equal(2)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(2)
- const video = res.body.data.find(v => v.uuid === video2UUID)
+ const video = data.find(v => v.uuid === video2UUID)
expect(video).not.to.be.undefined
expect(video.name).to.equal('video 2 updated')
}
import 'mocha'
import * as chai from 'chai'
-import { FfprobeData } from 'fluent-ffmpeg'
import { omit } from 'lodash'
-import { join } from 'path'
-import { Job } from '@shared/models'
-import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
buildAbsoluteFixturePath,
- buildServerDirectory,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
generateHighBitrateVideo,
generateVideoWithFramerate,
- getJobsListPaginationAndSort,
- getMyVideos,
- getServerFileSize,
- getVideo,
- getVideoFileMetadataUrl,
- getVideosList,
+ getFileSize,
makeGetRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateCustomSubConfig,
- uploadVideo,
- uploadVideoAndGetId,
waitJobs,
webtorrentAdd
-} from '../../../../shared/extra-utils'
-import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos'
+} from '@shared/extra-utils'
+import { getMaxBitrate, HttpStatusCode, VideoResolution, VideoState } from '@shared/models'
+import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants'
import {
canDoQuickTranscode,
getAudioStream,
const expect = chai.expect
-function updateConfigForTranscoding (server: ServerInfo) {
- return updateCustomSubConfig(server.url, server.accessToken, {
- transcoding: {
- enabled: true,
- allowAdditionalExtensions: true,
- allowAudioFiles: true,
- hls: { enabled: true },
- webtorrent: { enabled: true },
- resolutions: {
- '0p': false,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
+function updateConfigForTranscoding (server: PeerTubeServer) {
+ return server.config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: true,
+ allowAdditionalExtensions: true,
+ allowAudioFiles: true,
+ hls: { enabled: true },
+ webtorrent: { enabled: true },
+ resolutions: {
+ '0p': false,
+ '240p': true,
+ '360p': true,
+ '480p': true,
+ '720p': true,
+ '1080p': true,
+ '1440p': true,
+ '2160p': true
+ }
}
}
})
}
describe('Test video transcoding', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let video4k: string
before(async function () {
this.timeout(30_000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
it('Should not transcode video on server 1', async function () {
this.timeout(60_000)
- const videoAttributes = {
+ const attributes = {
name: 'my super name for server 1',
description: 'my super description for server 1',
fixture: 'video_short.webm'
}
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ await servers[0].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const video = res.body.data[0]
+ const { data } = await server.videos.list()
+ const video = data[0]
- const res2 = await getVideo(server.url, video.id)
- const videoDetails = res2.body
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(1)
const magnetUri = videoDetails.files[0].magnetUri
it('Should transcode video on server 2', async function () {
this.timeout(120_000)
- const videoAttributes = {
+ const attributes = {
name: 'my super name for server 2',
description: 'my super description for server 2',
fixture: 'video_short.webm'
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails = res2.body
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(4)
{
// Upload the video, but wait transcoding
- const videoAttributes = {
+ const attributes = {
name: 'waiting video',
fixture: 'video_short1.webm',
waitTranscoding: true
}
- const resVideo = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
- const videoId = resVideo.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes })
+ const videoId = uuid
// Should be in transcode state
- const { body } = await getVideo(servers[1].url, videoId)
+ const body = await servers[1].videos.get({ id: videoId })
expect(body.name).to.equal('waiting video')
expect(body.state.id).to.equal(VideoState.TO_TRANSCODE)
expect(body.state.label).to.equal('To transcode')
expect(body.waitTranscoding).to.be.true
- // Should have my video
- const resMyVideos = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 10)
- const videoToFindInMine = resMyVideos.body.data.find(v => v.name === videoAttributes.name)
- expect(videoToFindInMine).not.to.be.undefined
- expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE)
- expect(videoToFindInMine.state.label).to.equal('To transcode')
- expect(videoToFindInMine.waitTranscoding).to.be.true
+ {
+ // Should have my video
+ const { data } = await servers[1].videos.listMyVideos()
+ const videoToFindInMine = data.find(v => v.name === attributes.name)
+ expect(videoToFindInMine).not.to.be.undefined
+ expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE)
+ expect(videoToFindInMine.state.label).to.equal('To transcode')
+ expect(videoToFindInMine.waitTranscoding).to.be.true
+ }
- // Should not list this video
- const resVideos = await getVideosList(servers[1].url)
- const videoToFindInList = resVideos.body.data.find(v => v.name === videoAttributes.name)
- expect(videoToFindInList).to.be.undefined
+ {
+ // Should not list this video
+ const { data } = await servers[1].videos.list()
+ const videoToFindInList = data.find(v => v.name === attributes.name)
+ expect(videoToFindInList).to.be.undefined
+ }
// Server 1 should not have the video yet
- await getVideo(servers[0].url, videoId, HttpStatusCode.NOT_FOUND_404)
+ await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videoToFind = res.body.data.find(v => v.name === 'waiting video')
+ const { data } = await server.videos.list()
+ const videoToFind = data.find(v => v.name === 'waiting video')
expect(videoToFind).not.to.be.undefined
- const res2 = await getVideo(server.url, videoToFind.id)
- const videoDetails: VideoDetails = res2.body
+ const videoDetails = await server.videos.get({ id: videoToFind.id })
expect(videoDetails.state.id).to.equal(VideoState.PUBLISHED)
expect(videoDetails.state.label).to.equal('Published')
}
for (const fixture of [ 'video_short.mkv', 'video_short.avi' ]) {
- const videoAttributes = {
+ const attributes = {
name: fixture,
fixture
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
-
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails = res2.body
+ const { data } = await server.videos.list()
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(4)
const magnetUri = videoDetails.files[0].magnetUri
it('Should transcode a 4k video', async function () {
this.timeout(200_000)
- const videoAttributes = {
+ const attributes = {
name: '4k video',
fixture: 'video_short_4k.mp4'
}
- const resUpload = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
- video4k = resUpload.body.video.uuid
+ const { uuid } = await servers[1].videos.upload({ attributes })
+ video4k = uuid
await waitJobs(servers)
const resolutions = [ 240, 360, 480, 720, 1080, 1440, 2160 ]
for (const server of servers) {
- const res = await getVideo(server.url, video4k)
- const videoDetails: VideoDetails = res.body
-
+ const videoDetails = await server.videos.get({ id: video4k })
expect(videoDetails.files).to.have.lengthOf(resolutions.length)
for (const r of resolutions) {
it('Should transcode high bit rate mp3 to proper bit rate', async function () {
this.timeout(60_000)
- const videoAttributes = {
+ const attributes = {
name: 'mp3_256k',
fixture: 'video_short_mp3_256k.mp4'
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(4)
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4'))
+ const file = videoDetails.files.find(f => f.resolution.id === 240)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const probe = await getAudioStream(path)
if (probe.audioStream) {
it('Should transcode video with no audio and have no audio itself', async function () {
this.timeout(60_000)
- const videoAttributes = {
+ const attributes = {
name: 'no_audio',
fixture: 'video_short_no_audio.mp4'
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
+
+ const file = videoDetails.files.find(f => f.resolution.id === 240)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
- expect(videoDetails.files).to.have.lengthOf(4)
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4'))
const probe = await getAudioStream(path)
expect(probe).to.not.have.property('audioStream')
}
it('Should leave the audio untouched, but properly transcode the video', async function () {
this.timeout(60_000)
- const videoAttributes = {
+ const attributes = {
name: 'untouched_audio',
fixture: 'video_short.mp4'
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(4)
- const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture)
+ const fixturePath = buildAbsoluteFixturePath(attributes.fixture)
const fixtureVideoProbe = await getAudioStream(fixturePath)
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4'))
+
+ const file = videoDetails.files.find(f => f.resolution.id === 240)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const videoProbe = await getAudioStream(path)
function runSuite (mode: 'legacy' | 'resumable') {
before(async function () {
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, {
- transcoding: {
- hls: { enabled: true },
- webtorrent: { enabled: true },
- resolutions: {
- '0p': false,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
+ await servers[1].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ hls: { enabled: true },
+ webtorrent: { enabled: true },
+ resolutions: {
+ '0p': false,
+ '240p': false,
+ '360p': false,
+ '480p': false,
+ '720p': false,
+ '1080p': false,
+ '1440p': false,
+ '2160p': false
+ }
}
}
})
it('Should merge an audio file with the preview file', async function () {
this.timeout(60_000)
- const videoAttributesArg = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode)
+ const attributes = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
+ await servers[1].videos.upload({ attributes, mode })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === 'audio_with_preview')
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ const video = data.find(v => v.name === 'audio_with_preview')
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(1)
- await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, statusCodeExpected: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: videoDetails.previewPath, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
const magnetUri = videoDetails.files[0].magnetUri
expect(magnetUri).to.contain('.mp4')
it('Should upload an audio file and choose a default background image', async function () {
this.timeout(60_000)
- const videoAttributesArg = { name: 'audio_without_preview', fixture: 'sample.ogg' }
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode)
+ const attributes = { name: 'audio_without_preview', fixture: 'sample.ogg' }
+ await servers[1].videos.upload({ attributes, mode })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === 'audio_without_preview')
- const res2 = await getVideo(server.url, video.id)
- const videoDetails = res2.body
+ const video = data.find(v => v.name === 'audio_without_preview')
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(1)
- await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, statusCodeExpected: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: videoDetails.previewPath, statusCodeExpected: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
+ await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
const magnetUri = videoDetails.files[0].magnetUri
expect(magnetUri).to.contain('.mp4')
it('Should upload an audio file and create an audio version only', async function () {
this.timeout(60_000)
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, {
- transcoding: {
- hls: { enabled: true },
- webtorrent: { enabled: true },
- resolutions: {
- '0p': true,
- '240p': false,
- '360p': false
+ await servers[1].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ hls: { enabled: true },
+ webtorrent: { enabled: true },
+ resolutions: {
+ '0p': true,
+ '240p': false,
+ '360p': false
+ }
}
}
})
- const videoAttributesArg = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
- const resVideo = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode)
+ const attributes = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
+ const { id } = await servers[1].videos.upload({ attributes, mode })
await waitJobs(servers)
for (const server of servers) {
- const res2 = await getVideo(server.url, resVideo.body.video.id)
- const videoDetails: VideoDetails = res2.body
+ const videoDetails = await server.videos.get({ id })
for (const files of [ videoDetails.files, videoDetails.streamingPlaylists[0].files ]) {
expect(files).to.have.lengthOf(2)
it('Should transcode a 60 FPS video', async function () {
this.timeout(60_000)
- const videoAttributes = {
+ const attributes = {
name: 'my super 30fps name for server 2',
description: 'my super 30fps description for server 2',
fixture: '60fps_720p_small.mp4'
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ const video = data.find(v => v.name === attributes.name)
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.files).to.have.lengthOf(4)
expect(videoDetails.files[0].fps).to.be.above(58).and.below(62)
expect(videoDetails.files[2].fps).to.be.below(31)
expect(videoDetails.files[3].fps).to.be.below(31)
- for (const resolution of [ '240', '360', '480' ]) {
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-' + resolution + '.mp4'))
+ for (const resolution of [ 240, 360, 480 ]) {
+ const file = videoDetails.files.find(f => f.resolution.id === resolution)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const fps = await getVideoFileFPS(path)
expect(fps).to.be.below(31)
}
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-720.mp4'))
+ const file = videoDetails.files.find(f => f.resolution.id === 720)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const fps = await getVideoFileFPS(path)
expect(fps).to.be.above(58).and.below(62)
expect(fps).to.be.equal(59)
}
- const videoAttributes = {
+ const attributes = {
name: '59fps video',
description: '59fps video',
fixture: tempFixturePath
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
+ const { id } = data.find(v => v.name === attributes.name)
+ const video = await server.videos.get({ id })
{
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4'))
+ const file = video.files.find(f => f.resolution.id === 240)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const fps = await getVideoFileFPS(path)
expect(fps).to.be.equal(25)
}
{
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-720.mp4'))
+ const file = video.files.find(f => f.resolution.id === 720)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const fps = await getVideoFileFPS(path)
expect(fps).to.be.equal(59)
}
})
describe('Bitrate control', function () {
+
it('Should respect maximum bitrate values', async function () {
this.timeout(160_000)
expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 25, VIDEO_TRANSCODING_FPS))
}
- const videoAttributes = {
+ const attributes = {
name: 'high bitrate video',
description: 'high bitrate video',
fixture: tempFixturePath
}
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ await servers[1].videos.upload({ attributes })
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.name === videoAttributes.name)
+ const { id } = data.find(v => v.name === attributes.name)
+ const video = await server.videos.get({ id })
- for (const resolution of [ '240', '360', '480', '720', '1080' ]) {
- const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-' + resolution + '.mp4'))
+ for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
+ const file = video.files.find(f => f.resolution.id === resolution)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const bitrate = await getVideoFileBitrate(path)
const fps = await getVideoFileFPS(path)
- const resolution2 = await getVideoFileResolution(path)
+ const { videoFileResolution } = await getVideoFileResolution(path)
- expect(resolution2.videoFileResolution.toString()).to.equal(resolution)
- expect(bitrate).to.be.below(getMaxBitrate(resolution2.videoFileResolution, fps, VIDEO_TRANSCODING_FPS))
+ expect(videoFileResolution).to.equal(resolution)
+ expect(bitrate).to.be.below(getMaxBitrate(videoFileResolution, fps, VIDEO_TRANSCODING_FPS))
}
}
})
it('Should not transcode to an higher bitrate than the original file', async function () {
this.timeout(160_000)
- const config = {
+ const newConfig = {
transcoding: {
enabled: true,
resolutions: {
hls: { enabled: true }
}
}
- await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config)
+ await servers[1].config.updateCustomSubConfig({ newConfig })
- const videoAttributes = {
+ const attributes = {
name: 'low bitrate',
fixture: 'low-bitrate.mp4'
}
- const resUpload = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
- const videoUUID = resUpload.body.video.uuid
+ const { id } = await servers[1].videos.upload({ attributes })
await waitJobs(servers)
+ const video = await servers[1].videos.get({ id })
+
const resolutions = [ 240, 360, 480, 720, 1080 ]
for (const r of resolutions) {
- const path = `videos/${videoUUID}-${r}.mp4`
- const size = await getServerFileSize(servers[1], path)
+ const file = video.files.find(f => f.resolution.id === r)
+
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
+ const size = await getFileSize(path)
expect(size, `${path} not below ${60_000}`).to.be.below(60_000)
}
})
it('Should provide valid ffprobe data', async function () {
this.timeout(160_000)
- const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'ffprobe data' })).uuid
+ const videoUUID = (await servers[1].videos.quickUpload({ name: 'ffprobe data' })).uuid
await waitJobs(servers)
{
- const path = buildServerDirectory(servers[1], join('videos', videoUUID + '-240.mp4'))
+ const video = await servers[1].videos.get({ id: videoUUID })
+ const file = video.files.find(f => f.resolution.id === 240)
+ const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
const metadata = await getMetadataFromFile(path)
// expected format properties
}
for (const server of servers) {
- const res2 = await getVideo(server.url, videoUUID)
- const videoDetails: VideoDetails = res2.body
+ const videoDetails = await server.videos.get({ id: videoUUID })
const videoFiles = videoDetails.files
.concat(videoDetails.streamingPlaylists[0].files)
expect(file.metadataUrl).to.contain(servers[1].url)
expect(file.metadataUrl).to.contain(videoUUID)
- const res3 = await getVideoFileMetadataUrl(file.metadataUrl)
- const metadata: FfprobeData = res3.body
+ const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
expect(metadata).to.have.nested.property('format.size')
}
}
describe('Transcoding job queue', function () {
it('Should have the appropriate priorities for transcoding jobs', async function () {
- const res = await getJobsListPaginationAndSort({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
+ const body = await servers[1].jobs.getJobsList({
start: 0,
count: 100,
sort: '-createdAt',
jobType: 'video-transcoding'
})
- const jobs = res.body.data as Job[]
-
+ const jobs = body.data
const transcodingJobs = jobs.filter(j => j.data.videoUUID === video4k)
expect(transcodingJobs).to.have.lengthOf(14)
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import { expect } from 'chai'
import {
cleanupTests,
- createUser,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
makeGetRequest,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo,
- userLogin
-} from '../../../../shared/extra-utils'
-import { Video, VideoPrivacy } from '../../../../shared/models/videos'
-import { UserRole } from '../../../../shared/models/users'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
-
-const expect = chai.expect
-
-async function getVideosNames (server: ServerInfo, token: string, filter: string, statusCodeExpected = HttpStatusCode.OK_200) {
+ PeerTubeServer,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, UserRole, Video, VideoPrivacy } from '@shared/models'
+
+async function getVideosNames (server: PeerTubeServer, token: string, filter: string, expectedStatus = HttpStatusCode.OK_200) {
const paths = [
'/api/v1/video-channels/root_channel/videos',
'/api/v1/accounts/root/videos',
sort: 'createdAt',
filter
},
- statusCodeExpected
+ expectedStatus
})
videosResults.push(res.body.data.map(v => v.name))
}
describe('Test videos filter', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
// ---------------------------------------------------------------
before(async function () {
this.timeout(160000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
for (const server of servers) {
const moderator = { username: 'moderator', password: 'my super password' }
- await createUser(
- {
- url: server.url,
- accessToken: server.accessToken,
- username: moderator.username,
- password: moderator.password,
- videoQuota: undefined,
- videoQuotaDaily: undefined,
- role: UserRole.MODERATOR
- }
- )
- server['moderatorAccessToken'] = await userLogin(server, moderator)
+ await server.users.create({ username: moderator.username, password: moderator.password, role: UserRole.MODERATOR })
+ server['moderatorAccessToken'] = await server.login.getAccessToken(moderator)
- await uploadVideo(server.url, server.accessToken, { name: 'public ' + server.serverNumber })
+ await server.videos.upload({ attributes: { name: 'public ' + server.serverNumber } })
{
const attributes = { name: 'unlisted ' + server.serverNumber, privacy: VideoPrivacy.UNLISTED }
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes })
}
{
const attributes = { name: 'private ' + server.serverNumber, privacy: VideoPrivacy.PRIVATE }
- await uploadVideo(server.url, server.accessToken, attributes)
+ await server.videos.upload({ attributes })
}
}
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
cleanupTests,
- createUser,
- flushAndRunServer,
- getVideosListWithToken,
- getVideoWithToken,
+ createSingleServer,
+ HistoryCommand,
killallServers,
- reRunServer,
- searchVideoWithToken,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateMyUser,
- uploadVideo,
- userLogin,
wait
-} from '../../../../shared/extra-utils'
-import { Video, VideoDetails } from '../../../../shared/models/videos'
-import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode, Video } from '@shared/models'
const expect = chai.expect
describe('Test videos history', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer = null
let video1UUID: string
let video2UUID: string
let video3UUID: string
let video3WatchedDate: Date
let userAccessToken: string
+ let command: HistoryCommand
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
+ command = server.history
+
{
- const res = await uploadVideo(server.url, server.accessToken, { name: 'video 1' })
- video1UUID = res.body.video.uuid
+ const { uuid } = await server.videos.upload({ attributes: { name: 'video 1' } })
+ video1UUID = uuid
}
{
- const res = await uploadVideo(server.url, server.accessToken, { name: 'video 2' })
- video2UUID = res.body.video.uuid
+ const { uuid } = await server.videos.upload({ attributes: { name: 'video 2' } })
+ video2UUID = uuid
}
{
- const res = await uploadVideo(server.url, server.accessToken, { name: 'video 3' })
- video3UUID = res.body.video.uuid
+ const { uuid } = await server.videos.upload({ attributes: { name: 'video 3' } })
+ video3UUID = uuid
}
const user = {
username: 'user_1',
password: 'super password'
}
- await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
- userAccessToken = await userLogin(server, user)
+ await server.users.create({ username: user.username, password: user.password })
+ userAccessToken = await server.login.getAccessToken(user)
})
it('Should get videos, without watching history', async function () {
- const res = await getVideosListWithToken(server.url, server.accessToken)
- const videos: Video[] = res.body.data
+ const { data } = await server.videos.listWithToken()
- for (const video of videos) {
- const resDetail = await getVideoWithToken(server.url, server.accessToken, video.id)
- const videoDetails: VideoDetails = resDetail.body
+ for (const video of data) {
+ const videoDetails = await server.videos.getWithToken({ id: video.id })
expect(video.userHistory).to.be.undefined
expect(videoDetails.userHistory).to.be.undefined
})
it('Should watch the first and second video', async function () {
- await userWatchVideo(server.url, server.accessToken, video2UUID, 8)
- await userWatchVideo(server.url, server.accessToken, video1UUID, 3)
+ await command.wathVideo({ videoId: video2UUID, currentTime: 8 })
+ await command.wathVideo({ videoId: video1UUID, currentTime: 3 })
})
it('Should return the correct history when listing, searching and getting videos', async function () {
const videosOfVideos: Video[][] = []
{
- const res = await getVideosListWithToken(server.url, server.accessToken)
- videosOfVideos.push(res.body.data)
+ const { data } = await server.videos.listWithToken()
+ videosOfVideos.push(data)
}
{
- const res = await searchVideoWithToken(server.url, 'video', server.accessToken)
- videosOfVideos.push(res.body.data)
+ const body = await server.search.searchVideos({ token: server.accessToken, search: 'video' })
+ videosOfVideos.push(body.data)
}
for (const videos of videosOfVideos) {
}
{
- const resDetail = await getVideoWithToken(server.url, server.accessToken, video1UUID)
- const videoDetails: VideoDetails = resDetail.body
+ const videoDetails = await server.videos.getWithToken({ id: video1UUID })
expect(videoDetails.userHistory).to.not.be.undefined
expect(videoDetails.userHistory.currentTime).to.equal(3)
}
{
- const resDetail = await getVideoWithToken(server.url, server.accessToken, video2UUID)
- const videoDetails: VideoDetails = resDetail.body
+ const videoDetails = await server.videos.getWithToken({ id: video2UUID })
expect(videoDetails.userHistory).to.not.be.undefined
expect(videoDetails.userHistory.currentTime).to.equal(8)
}
{
- const resDetail = await getVideoWithToken(server.url, server.accessToken, video3UUID)
- const videoDetails: VideoDetails = resDetail.body
+ const videoDetails = await server.videos.getWithToken({ id: video3UUID })
expect(videoDetails.userHistory).to.be.undefined
}
it('Should have these videos when listing my history', async function () {
video3WatchedDate = new Date()
- await userWatchVideo(server.url, server.accessToken, video3UUID, 2)
+ await command.wathVideo({ videoId: video3UUID, currentTime: 2 })
- const res = await listMyVideosHistory(server.url, server.accessToken)
+ const body = await command.list()
- expect(res.body.total).to.equal(3)
+ expect(body.total).to.equal(3)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 3')
expect(videos[1].name).to.equal('video 1')
expect(videos[2].name).to.equal('video 2')
})
it('Should not have videos history on another user', async function () {
- const res = await listMyVideosHistory(server.url, userAccessToken)
+ const body = await command.list({ token: userAccessToken })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
+ expect(body.total).to.equal(0)
+ expect(body.data).to.have.lengthOf(0)
})
it('Should be able to search through videos in my history', async function () {
- const res = await listMyVideosHistory(server.url, server.accessToken, '2')
-
- expect(res.body.total).to.equal(1)
+ const body = await command.list({ search: '2' })
+ expect(body.total).to.equal(1)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 2')
})
it('Should clear my history', async function () {
- await removeMyVideosHistory(server.url, server.accessToken, video3WatchedDate.toISOString())
+ await command.remove({ beforeDate: video3WatchedDate.toISOString() })
})
it('Should have my history cleared', async function () {
- const res = await listMyVideosHistory(server.url, server.accessToken)
+ const body = await command.list()
+ expect(body.total).to.equal(1)
- expect(res.body.total).to.equal(1)
-
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 3')
})
it('Should disable videos history', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: server.accessToken,
+ await server.users.updateMe({
videosHistoryEnabled: false
})
- await userWatchVideo(server.url, server.accessToken, video2UUID, 8, HttpStatusCode.CONFLICT_409)
+ await command.wathVideo({ videoId: video2UUID, currentTime: 8, expectedStatus: HttpStatusCode.CONFLICT_409 })
})
it('Should re-enable videos history', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: server.accessToken,
+ await server.users.updateMe({
videosHistoryEnabled: true
})
- await userWatchVideo(server.url, server.accessToken, video1UUID, 8)
-
- const res = await listMyVideosHistory(server.url, server.accessToken)
+ await command.wathVideo({ videoId: video1UUID, currentTime: 8 })
- expect(res.body.total).to.equal(2)
+ const body = await command.list()
+ expect(body.total).to.equal(2)
- const videos: Video[] = res.body.data
+ const videos = body.data
expect(videos[0].name).to.equal('video 1')
expect(videos[1].name).to.equal('video 3')
})
it('Should not clean old history', async function () {
this.timeout(50000)
- killallServers([ server ])
+ await killallServers([ server ])
- await reRunServer(server, { history: { videos: { max_age: '10 days' } } })
+ await server.run({ history: { videos: { max_age: '10 days' } } })
await wait(6000)
// Should still have history
- const res = await listMyVideosHistory(server.url, server.accessToken)
-
- expect(res.body.total).to.equal(2)
+ const body = await command.list()
+ expect(body.total).to.equal(2)
})
it('Should clean old history', async function () {
this.timeout(50000)
- killallServers([ server ])
+ await killallServers([ server ])
- await reRunServer(server, { history: { videos: { max_age: '5 seconds' } } })
+ await server.run({ history: { videos: { max_age: '5 seconds' } } })
await wait(6000)
- const res = await listMyVideosHistory(server.url, server.accessToken)
- expect(res.body.total).to.equal(0)
+ const body = await command.list()
+ expect(body.total).to.equal(0)
})
after(async function () {
import 'mocha'
import * as chai from 'chai'
-
-import {
- cleanupTests,
- flushAndRunServer,
- generateUserAccessToken,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo,
- wait
-} from '../../../../shared/extra-utils'
-import { getVideosOverview, getVideosOverviewWithToken } from '../../../../shared/extra-utils/overviews/overviews'
-import { VideosOverview } from '../../../../shared/models/overviews'
-import { addAccountToAccountBlocklist } from '@shared/extra-utils/users/blocklist'
-import { Response } from 'superagent'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { VideosOverview } from '@shared/models'
const expect = chai.expect
describe('Test a videos overview', function () {
- let server: ServerInfo = null
-
- function testOverviewCount (res: Response, expected: number) {
- const overview: VideosOverview = res.body
+ let server: PeerTubeServer = null
+ function testOverviewCount (overview: VideosOverview, expected: number) {
expect(overview.tags).to.have.lengthOf(expected)
expect(overview.categories).to.have.lengthOf(expected)
expect(overview.channels).to.have.lengthOf(expected)
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
it('Should send empty overview', async function () {
- const res = await getVideosOverview(server.url, 1)
+ const body = await server.overviews.getVideos({ page: 1 })
- testOverviewCount(res, 0)
+ testOverviewCount(body, 0)
})
it('Should upload 5 videos in a specific category, tag and channel but not include them in overview', async function () {
await wait(3000)
- await uploadVideo(server.url, server.accessToken, {
- name: 'video 0',
- category: 3,
- tags: [ 'coucou1', 'coucou2' ]
+ await server.videos.upload({
+ attributes: {
+ name: 'video 0',
+ category: 3,
+ tags: [ 'coucou1', 'coucou2' ]
+ }
})
- const res = await getVideosOverview(server.url, 1)
+ const body = await server.overviews.getVideos({ page: 1 })
- testOverviewCount(res, 0)
+ testOverviewCount(body, 0)
})
it('Should upload another video and include all videos in the overview', async function () {
this.timeout(30000)
- for (let i = 1; i < 6; i++) {
- await uploadVideo(server.url, server.accessToken, {
- name: 'video ' + i,
- category: 3,
- tags: [ 'coucou1', 'coucou2' ]
- })
+ {
+ for (let i = 1; i < 6; i++) {
+ await server.videos.upload({
+ attributes: {
+ name: 'video ' + i,
+ category: 3,
+ tags: [ 'coucou1', 'coucou2' ]
+ }
+ })
+ }
+
+ await wait(3000)
}
- await wait(3000)
-
{
- const res = await getVideosOverview(server.url, 1)
+ const body = await server.overviews.getVideos({ page: 1 })
- testOverviewCount(res, 1)
+ testOverviewCount(body, 1)
}
{
- const res = await getVideosOverview(server.url, 2)
+ const overview = await server.overviews.getVideos({ page: 2 })
- const overview: VideosOverview = res.body
expect(overview.tags).to.have.lengthOf(1)
expect(overview.categories).to.have.lengthOf(0)
expect(overview.channels).to.have.lengthOf(0)
})
it('Should have the correct overview', async function () {
- const res1 = await getVideosOverview(server.url, 1)
- const res2 = await getVideosOverview(server.url, 2)
-
- const overview1: VideosOverview = res1.body
- const overview2: VideosOverview = res2.body
-
- const tmp = [
- overview1.tags,
- overview1.categories,
- overview1.channels,
- overview2.tags
- ]
+ const overview1 = await server.overviews.getVideos({ page: 1 })
+ const overview2 = await server.overviews.getVideos({ page: 2 })
- for (const arr of tmp) {
+ for (const arr of [ overview1.tags, overview1.categories, overview1.channels, overview2.tags ]) {
expect(arr).to.have.lengthOf(1)
const obj = arr[0]
})
it('Should hide muted accounts', async function () {
- const token = await generateUserAccessToken(server, 'choco')
+ const token = await server.users.generateUserAndToken('choco')
- await addAccountToAccountBlocklist(server.url, token, 'root@' + server.host)
+ await server.blocklist.addToMyBlocklist({ token, account: 'root@' + server.host })
{
- const res = await getVideosOverview(server.url, 1)
+ const body = await server.overviews.getVideos({ page: 1 })
- testOverviewCount(res, 1)
+ testOverviewCount(body, 1)
}
{
- const res = await getVideosOverviewWithToken(server.url, 1, token)
+ const body = await server.overviews.getVideos({ page: 1, token })
- testOverviewCount(res, 0)
+ testOverviewCount(body, 0)
}
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import {
cleanupTests,
- closeAllSequelize,
- countVideoViewsOf,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
killallServers,
- reRunServer,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideoAndGetId,
- viewVideo,
wait,
waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
describe('Test video views cleaner', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoIdServer1: string
let videoIdServer2: string
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
- videoIdServer1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })).uuid
- videoIdServer2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })).uuid
+ videoIdServer1 = (await servers[0].videos.quickUpload({ name: 'video server 1' })).uuid
+ videoIdServer2 = (await servers[1].videos.quickUpload({ name: 'video server 2' })).uuid
await waitJobs(servers)
- await viewVideo(servers[0].url, videoIdServer1)
- await viewVideo(servers[1].url, videoIdServer1)
- await viewVideo(servers[0].url, videoIdServer2)
- await viewVideo(servers[1].url, videoIdServer2)
+ await servers[0].videos.view({ id: videoIdServer1 })
+ await servers[1].videos.view({ id: videoIdServer1 })
+ await servers[0].videos.view({ id: videoIdServer2 })
+ await servers[1].videos.view({ id: videoIdServer2 })
await waitJobs(servers)
})
it('Should not clean old video views', async function () {
this.timeout(50000)
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
- await reRunServer(servers[0], { views: { videos: { remote: { max_age: '10 days' } } } })
+ await servers[0].run({ views: { videos: { remote: { max_age: '10 days' } } } })
await wait(6000)
{
for (const server of servers) {
- const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer1)
+ const total = await server.sql.countVideoViewsOf(videoIdServer1)
expect(total).to.equal(2, 'Server ' + server.serverNumber + ' does not have the correct amount of views')
}
}
{
for (const server of servers) {
- const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer2)
+ const total = await server.sql.countVideoViewsOf(videoIdServer2)
expect(total).to.equal(2, 'Server ' + server.serverNumber + ' does not have the correct amount of views')
}
}
it('Should clean old video views', async function () {
this.timeout(50000)
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
- await reRunServer(servers[0], { views: { videos: { remote: { max_age: '5 seconds' } } } })
+ await servers[0].run({ views: { videos: { remote: { max_age: '5 seconds' } } } })
await wait(6000)
{
for (const server of servers) {
- const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer1)
+ const total = await server.sql.countVideoViewsOf(videoIdServer1)
expect(total).to.equal(2)
}
}
{
- const totalServer1 = await countVideoViewsOf(servers[0].internalServerNumber, videoIdServer2)
+ const totalServer1 = await servers[0].sql.countVideoViewsOf(videoIdServer2)
expect(totalServer1).to.equal(0)
- const totalServer2 = await countVideoViewsOf(servers[1].internalServerNumber, videoIdServer2)
+ const totalServer2 = await servers[1].sql.countVideoViewsOf(videoIdServer2)
expect(totalServer2).to.equal(2)
}
})
after(async function () {
- await closeAllSequelize(servers)
-
await cleanupTests(servers)
})
})
import 'mocha'
import * as chai from 'chai'
-import { VideoFile } from '@shared/models/videos/video-file.model'
-import {
- cleanupTests,
- doubleFollow,
- execCLI,
- flushAndRunMultipleServers,
- getEnvCli,
- getVideo,
- getVideosList,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '../../../shared/extra-utils'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
-import { VideoDetails } from '../../../shared/models/videos'
+import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { VideoFile } from '@shared/models'
const expect = chai.expect
describe('Test create import video jobs', function () {
this.timeout(60000)
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let video1UUID: string
let video2UUID: string
this.timeout(90000)
// Run server 2 to have transcoding enabled
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
// Upload two videos for our needs
- const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1' })
- video1UUID = res1.body.video.uuid
- const res2 = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video2' })
- video2UUID = res2.body.video.uuid
+ {
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video1' } })
+ video1UUID = uuid
+ }
+
+ {
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video2' } })
+ video2UUID = uuid
+ }
// Transcoding
await waitJobs(servers)
})
it('Should run a import job on video 1 with a lower resolution', async function () {
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-import-video-file-job -- -v ${video1UUID} -i server/tests/fixtures/video_short-480.webm`)
+ const command = `npm run create-import-video-file-job -- -v ${video1UUID} -i server/tests/fixtures/video_short-480.webm`
+ await servers[0].cli.execWithEnv(command)
await waitJobs(servers)
for (const server of servers) {
- const { data: videos } = (await getVideosList(server.url)).body
+ const { data: videos } = await server.videos.list()
expect(videos).to.have.lengthOf(2)
const video = videos.find(({ uuid }) => uuid === video1UUID)
- const videoDetail: VideoDetails = (await getVideo(server.url, video.uuid)).body
+ const videoDetails = await server.videos.get({ id: video.uuid })
- expect(videoDetail.files).to.have.lengthOf(2)
- const [ originalVideo, transcodedVideo ] = videoDetail.files
+ expect(videoDetails.files).to.have.lengthOf(2)
+ const [ originalVideo, transcodedVideo ] = videoDetails.files
assertVideoProperties(originalVideo, 720, 'webm', 218910)
assertVideoProperties(transcodedVideo, 480, 'webm', 69217)
}
})
it('Should run a import job on video 2 with the same resolution and a different extension', async function () {
- const env = getEnvCli(servers[1])
- await execCLI(`${env} npm run create-import-video-file-job -- -v ${video2UUID} -i server/tests/fixtures/video_short.ogv`)
+ const command = `npm run create-import-video-file-job -- -v ${video2UUID} -i server/tests/fixtures/video_short.ogv`
+ await servers[1].cli.execWithEnv(command)
await waitJobs(servers)
for (const server of servers) {
- const { data: videos } = (await getVideosList(server.url)).body
+ const { data: videos } = await server.videos.list()
expect(videos).to.have.lengthOf(2)
const video = videos.find(({ uuid }) => uuid === video2UUID)
- const videoDetail: VideoDetails = (await getVideo(server.url, video.uuid)).body
+ const videoDetails = await server.videos.get({ id: video.uuid })
- expect(videoDetail.files).to.have.lengthOf(4)
- const [ originalVideo, transcodedVideo420, transcodedVideo320, transcodedVideo240 ] = videoDetail.files
+ expect(videoDetails.files).to.have.lengthOf(4)
+ const [ originalVideo, transcodedVideo420, transcodedVideo320, transcodedVideo240 ] = videoDetails.files
assertVideoProperties(originalVideo, 720, 'ogv', 140849)
assertVideoProperties(transcodedVideo420, 480, 'mp4')
assertVideoProperties(transcodedVideo320, 360, 'mp4')
})
it('Should run a import job on video 2 with the same resolution and the same extension', async function () {
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-import-video-file-job -- -v ${video1UUID} -i server/tests/fixtures/video_short2.webm`)
+ const command = `npm run create-import-video-file-job -- -v ${video1UUID} -i server/tests/fixtures/video_short2.webm`
+ await servers[0].cli.execWithEnv(command)
await waitJobs(servers)
for (const server of servers) {
- const { data: videos } = (await getVideosList(server.url)).body
+ const { data: videos } = await server.videos.list()
expect(videos).to.have.lengthOf(2)
const video = videos.find(({ uuid }) => uuid === video1UUID)
- const videoDetail: VideoDetails = (await getVideo(server.url, video.uuid)).body
+ const videoDetails = await server.videos.get({ id: video.uuid })
- expect(videoDetail.files).to.have.lengthOf(2)
- const [ video720, video480 ] = videoDetail.files
+ expect(videoDetails.files).to.have.lengthOf(2)
+ const [ video720, video480 ] = videoDetails.files
assertVideoProperties(video720, 720, 'webm', 942961)
assertVideoProperties(video480, 480, 'webm', 69217)
}
import 'mocha'
import * as chai from 'chai'
-import { VideoDetails } from '../../../shared/models/videos'
import {
cleanupTests,
+ createMultipleServers,
doubleFollow,
- execCLI,
- flushAndRunMultipleServers,
- getEnvCli,
- getVideo,
- getVideosList,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- updateCustomSubConfig,
- uploadVideo
+ waitJobs
} from '../../../shared/extra-utils'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
const expect = chai.expect
describe('Test create transcoding jobs', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
const videosUUID: string[] = []
const config = {
this.timeout(60000)
// Run server 2 to have transcoding enabled
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
await doubleFollow(servers[0], servers[1])
for (let i = 1; i <= 5; i++) {
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' + i })
- videosUUID.push(res.body.video.uuid)
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' + i } })
+ videosUUID.push(uuid)
}
await waitJobs(servers)
this.timeout(30000)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(videosUUID.length)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(videosUUID.length)
- for (const video of videos) {
- const res2 = await getVideo(server.url, video.uuid)
- const videoDetail: VideoDetails = res2.body
+ for (const video of data) {
+ const videoDetail = await server.videos.get({ id: video.uuid })
expect(videoDetail.files).to.have.lengthOf(1)
expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
}
it('Should run a transcoding job on video 2', async function () {
this.timeout(60000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[1]}`)
-
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[1]}`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
+ const { data } = await server.videos.list()
let infoHashes: { [id: number]: string }
- for (const video of videos) {
- const res2 = await getVideo(server.url, video.uuid)
- const videoDetail: VideoDetails = res2.body
+ for (const video of data) {
+ const videoDetail = await server.videos.get({ id: video.uuid })
if (video.uuid === videosUUID[1]) {
expect(videoDetail.files).to.have.lengthOf(4)
it('Should run a transcoding job on video 1 with resolution', async function () {
this.timeout(60000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[0]} -r 480`)
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[0]} -r 480`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(videosUUID.length)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(videosUUID.length)
- const res2 = await getVideo(server.url, videosUUID[0])
- const videoDetail: VideoDetails = res2.body
+ const videoDetails = await server.videos.get({ id: videosUUID[0] })
- expect(videoDetail.files).to.have.lengthOf(2)
- expect(videoDetail.files[0].resolution.id).to.equal(720)
- expect(videoDetail.files[1].resolution.id).to.equal(480)
+ expect(videoDetails.files).to.have.lengthOf(2)
+ expect(videoDetails.files[0].resolution.id).to.equal(720)
+ expect(videoDetails.files[1].resolution.id).to.equal(480)
- expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
+ expect(videoDetails.streamingPlaylists).to.have.lengthOf(0)
}
})
it('Should generate an HLS resolution', async function () {
this.timeout(120000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videosUUID[2])
- const videoDetail: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: videosUUID[2] })
- expect(videoDetail.files).to.have.lengthOf(1)
- expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
+ expect(videoDetails.files).to.have.lengthOf(1)
+ expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- const files = videoDetail.streamingPlaylists[0].files
+ const files = videoDetails.streamingPlaylists[0].files
expect(files).to.have.lengthOf(1)
expect(files[0].resolution.id).to.equal(480)
}
it('Should not duplicate an HLS resolution', async function () {
this.timeout(120000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videosUUID[2])
- const videoDetail: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: videosUUID[2] })
- const files = videoDetail.streamingPlaylists[0].files
+ const files = videoDetails.streamingPlaylists[0].files
expect(files).to.have.lengthOf(1)
expect(files[0].resolution.id).to.equal(480)
}
it('Should generate all HLS resolutions', async function () {
this.timeout(120000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[3]} --generate-hls`)
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[3]} --generate-hls`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videosUUID[3])
- const videoDetail: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: videosUUID[3] })
- expect(videoDetail.files).to.have.lengthOf(1)
- expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
+ expect(videoDetails.files).to.have.lengthOf(1)
+ expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- const files = videoDetail.streamingPlaylists[0].files
+ const files = videoDetails.streamingPlaylists[0].files
expect(files).to.have.lengthOf(4)
}
})
this.timeout(120000)
config.transcoding.hls.enabled = true
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomSubConfig({ newConfig: config })
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[4]}`)
+ await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[4]}`)
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideo(server.url, videosUUID[4])
- const videoDetail: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: videosUUID[4] })
- expect(videoDetail.files).to.have.lengthOf(4)
- expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetail.streamingPlaylists[0].files).to.have.lengthOf(4)
+ expect(videoDetails.files).to.have.lengthOf(4)
+ expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
+ expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(4)
}
})
import 'mocha'
import * as chai from 'chai'
-import { join } from 'path'
import {
- buildServerDirectory,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- execCLI,
- flushAndRunMultipleServers,
generateHighBitrateVideo,
- getEnvCli,
- getVideo,
- getVideosList,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo,
- viewVideo,
- wait
-} from '../../../shared/extra-utils'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
-import { getMaxBitrate, Video, VideoDetails, VideoResolution } from '../../../shared/models/videos'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { getMaxBitrate, VideoResolution } from '@shared/models'
import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../helpers/ffprobe-utils'
import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants'
const expect = chai.expect
describe('Test optimize old videos', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
before(async function () {
this.timeout(200000)
// Run server 2 to have transcoding enabled
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
}
// Upload two videos for our needs
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1', fixture: tempFixturePath })
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video2', fixture: tempFixturePath })
+ await servers[0].videos.upload({ attributes: { name: 'video1', fixture: tempFixturePath } })
+ await servers[0].videos.upload({ attributes: { name: 'video2', fixture: tempFixturePath } })
await waitJobs(servers)
})
this.timeout(30000)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(2)
-
- for (const video of videos) {
- const res2 = await getVideo(server.url, video.uuid)
- const videoDetail: VideoDetails = res2.body
- expect(videoDetail.files).to.have.lengthOf(1)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(2)
+
+ for (const video of data) {
+ const videoDetails = await server.videos.get({ id: video.uuid })
+ expect(videoDetails.files).to.have.lengthOf(1)
}
}
})
it('Should run optimize script', async function () {
this.timeout(200000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run optimize-old-videos`)
-
+ await servers[0].cli.execWithEnv('npm run optimize-old-videos')
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos: Video[] = res.body.data
-
- expect(videos).to.have.lengthOf(2)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(2)
- for (const video of videos) {
- await viewVideo(server.url, video.uuid)
+ for (const video of data) {
+ await server.videos.view({ id: video.uuid })
// Refresh video
await waitJobs(servers)
await wait(5000)
await waitJobs(servers)
- const res2 = await getVideo(server.url, video.uuid)
- const videosDetails: VideoDetails = res2.body
+ const videoDetails = await server.videos.get({ id: video.uuid })
- expect(videosDetails.files).to.have.lengthOf(1)
- const file = videosDetails.files[0]
+ expect(videoDetails.files).to.have.lengthOf(1)
+ const file = videoDetails.files[0]
expect(file.size).to.be.below(8000000)
- const path = buildServerDirectory(servers[0], join('videos', video.uuid + '-' + file.resolution.id + '.mp4'))
+ const path = servers[0].servers.buildWebTorrentFilePath(file.fileUrl)
const bitrate = await getVideoFileBitrate(path)
const fps = await getVideoFileFPS(path)
const resolution = await getVideoFileResolution(path)
import 'mocha'
import { expect } from 'chai'
-import { Video, VideoDetails } from '../../../shared'
import {
- addVideoChannel,
areHttpImportTestsDisabled,
buildAbsoluteFixturePath,
cleanupTests,
- createUser,
+ CLICommand,
+ createSingleServer,
doubleFollow,
- execCLI,
- flushAndRunServer,
- getEnvCli,
- getLocalIdByUUID,
- getVideo,
- getVideosList,
- removeVideo,
- ServerInfo,
+ FIXTURE_URLS,
+ PeerTubeServer,
setAccessTokensToServers,
testHelloWorldRegisteredSettings,
- uploadVideoAndGetId,
- userLogin,
waitJobs
} from '../../../shared/extra-utils'
-import { getYoutubeVideoUrl } from '../../../shared/extra-utils/videos/video-imports'
describe('Test CLI wrapper', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let userAccessToken: string
+ let cliCommand: CLICommand
+
const cmd = 'node ./dist/server/tools/peertube.js'
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'user_1', password: 'super_password' })
+ await server.users.create({ username: 'user_1', password: 'super_password' })
- userAccessToken = await userLogin(server, { username: 'user_1', password: 'super_password' })
+ userAccessToken = await server.login.getAccessToken({ username: 'user_1', password: 'super_password' })
{
- const args = { name: 'user_channel', displayName: 'User channel', support: 'super support text' }
- await addVideoChannel(server.url, userAccessToken, args)
+ const attributes = { name: 'user_channel', displayName: 'User channel', support: 'super support text' }
+ await server.channels.create({ token: userAccessToken, attributes })
}
+
+ cliCommand = server.cli
})
describe('Authentication and instance selection', function () {
+ it('Should get an access token', async function () {
+ const stdout = await cliCommand.execWithEnv(`${cmd} token --url ${server.url} --username user_1 --password super_password`)
+ const token = stdout.trim()
+
+ const body = await server.users.getMyInfo({ token })
+ expect(body.username).to.equal('user_1')
+ })
+
it('Should display no selected instance', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- const stdout = await execCLI(`${env} ${cmd} --help`)
-
+ const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
expect(stdout).to.contain('no instance selected')
})
it('Should add a user', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
+ await cliCommand.execWithEnv(`${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
})
it('Should not fail to add a user if there is a slash at the end of the instance URL', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- let fullServerURL
- fullServerURL = server.url + '/'
- await execCLI(`${env} ${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
+ let fullServerURL = server.url + '/'
+
+ await cliCommand.execWithEnv(`${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
fullServerURL = server.url + '/asdfasdf'
- await execCLI(`${env} ${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
+ await cliCommand.execWithEnv(`${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
})
it('Should default to this user', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- const stdout = await execCLI(`${env} ${cmd} --help`)
-
+ const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
expect(stdout).to.contain(`instance ${server.url} selected`)
})
it('Should remember the user', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- const stdout = await execCLI(`${env} ${cmd} auth list`)
-
+ const stdout = await cliCommand.execWithEnv(`${cmd} auth list`)
expect(stdout).to.contain(server.url)
})
})
it('Should upload a video', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
-
const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
-
const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
- await execCLI(`${env} ${cmd} upload ${params}`)
+ await cliCommand.execWithEnv(`${cmd} upload ${params}`)
})
it('Should have the video uploaded', async function () {
- const res = await getVideosList(server.url)
-
- expect(res.body.total).to.equal(1)
-
- const videos: Video[] = res.body.data
-
- const video: VideoDetails = (await getVideo(server.url, videos[0].uuid)).body
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(1)
+ const video = await server.videos.get({ id: data[0].uuid })
expect(video.name).to.equal('test upload')
expect(video.support).to.equal('support_text')
expect(video.channel.name).to.equal('user_channel')
this.timeout(60000)
- const env = getEnvCli(server)
-
- const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
-
- await execCLI(`${env} ${cmd} import ${params}`)
+ const params = `--target-url ${FIXTURE_URLS.youtube} --channel-name user_channel`
+ await cliCommand.execWithEnv(`${cmd} import ${params}`)
})
it('Should have imported the video', async function () {
await waitJobs([ server ])
- const res = await getVideosList(server.url)
-
- expect(res.body.total).to.equal(2)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(2)
- const videos: Video[] = res.body.data
- const video = videos.find(v => v.name === 'small video - youtube')
+ const video = data.find(v => v.name === 'small video - youtube')
expect(video).to.not.be.undefined
- const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.channel.name).to.equal('user_channel')
expect(videoDetails.support).to.equal('super support text')
expect(videoDetails.nsfw).to.be.false
// So we can reimport it
- await removeVideo(server.url, userAccessToken, video.id)
+ await server.videos.remove({ token: userAccessToken, id: video.id })
})
it('Should import and override some imported attributes', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
-
- const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
-
- await execCLI(`${env} ${cmd} import ${params}`)
+ const params = `--target-url ${FIXTURE_URLS.youtube} ` +
+ `--channel-name user_channel --video-name toto --nsfw --support support`
+ await cliCommand.execWithEnv(`${cmd} import ${params}`)
await waitJobs([ server ])
{
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(2)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(2)
- const videos: Video[] = res.body.data
- const video = videos.find(v => v.name === 'toto')
+ const video = data.find(v => v.name === 'toto')
expect(video).to.not.be.undefined
- const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
+ const videoDetails = await server.videos.get({ id: video.id })
expect(videoDetails.channel.name).to.equal('user_channel')
expect(videoDetails.support).to.equal('support')
expect(videoDetails.nsfw).to.be.true
describe('Admin auth', function () {
it('Should remove the auth user', async function () {
- const env = getEnvCli(server)
-
- await execCLI(`${env} ${cmd} auth del ${server.url}`)
-
- const stdout = await execCLI(`${env} ${cmd} --help`)
+ await cliCommand.execWithEnv(`${cmd} auth del ${server.url}`)
+ const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
expect(stdout).to.contain('no instance selected')
})
it('Should add the admin user', async function () {
- const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} auth add -u ${server.url} -U root -p test${server.internalServerNumber}`)
+ await cliCommand.execWithEnv(`${cmd} auth add -u ${server.url} -U root -p test${server.internalServerNumber}`)
})
})
it('Should install a plugin', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} plugins install --npm-name peertube-plugin-hello-world`)
+ await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world`)
})
it('Should have registered settings', async function () {
})
it('Should list installed plugins', async function () {
- const env = getEnvCli(server)
- const res = await execCLI(`${env} ${cmd} plugins list`)
+ const res = await cliCommand.execWithEnv(`${cmd} plugins list`)
expect(res).to.contain('peertube-plugin-hello-world')
})
it('Should uninstall the plugin', async function () {
- const env = getEnvCli(server)
- const res = await execCLI(`${env} ${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
+ const res = await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
expect(res).to.not.contain('peertube-plugin-hello-world')
})
})
describe('Manage video redundancies', function () {
- let anotherServer: ServerInfo
+ let anotherServer: PeerTubeServer
let video1Server2: number
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
before(async function () {
this.timeout(120000)
- anotherServer = await flushAndRunServer(2)
+ anotherServer = await createSingleServer(2)
await setAccessTokensToServers([ anotherServer ])
await doubleFollow(server, anotherServer)
servers = [ server, anotherServer ]
await waitJobs(servers)
- const uuid = (await uploadVideoAndGetId({ server: anotherServer, videoName: 'super video' })).uuid
+ const { uuid } = await anotherServer.videos.quickUpload({ name: 'super video' })
await waitJobs(servers)
- video1Server2 = await getLocalIdByUUID(server.url, uuid)
+ video1Server2 = await server.videos.getId({ uuid })
})
it('Should add a redundancy', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
-
const params = `add --video ${video1Server2}`
-
- await execCLI(`${env} ${cmd} redundancy ${params}`)
+ await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
await waitJobs(servers)
})
this.timeout(60000)
{
- const env = getEnvCli(server)
-
const params = 'list-my-redundancies'
- const stdout = await execCLI(`${env} ${cmd} redundancy ${params}`)
+ const stdout = await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
expect(stdout).to.contain('super video')
expect(stdout).to.contain(`localhost:${server.port}`)
it('Should remove a redundancy', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
-
const params = `remove --video ${video1Server2}`
-
- await execCLI(`${env} ${cmd} redundancy ${params}`)
+ await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
await waitJobs(servers)
{
- const env = getEnvCli(server)
const params = 'list-my-redundancies'
- const stdout = await execCLI(`${env} ${cmd} redundancy ${params}`)
+ const stdout = await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
expect(stdout).to.not.contain('super video')
}
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
+import { expect } from 'chai'
import {
cleanupTests,
- execCLI,
- flushAndRunServer,
- getConfig,
- getEnvCli,
- getPluginTestPath,
+ createSingleServer,
killallServers,
- reRunServer,
- ServerInfo,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers
} from '../../../shared/extra-utils'
-import { ServerConfig } from '../../../shared/models/server'
-import { expect } from 'chai'
describe('Test plugin scripts', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
it('Should install a plugin from stateless CLI', async function () {
this.timeout(60000)
- const packagePath = getPluginTestPath()
+ const packagePath = PluginsCommand.getPluginTestPath()
- const env = getEnvCli(server)
- await execCLI(`${env} npm run plugin:install -- --plugin-path ${packagePath}`)
+ await server.cli.execWithEnv(`npm run plugin:install -- --plugin-path ${packagePath}`)
})
it('Should install a theme from stateless CLI', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- await execCLI(`${env} npm run plugin:install -- --npm-name peertube-theme-background-red`)
+ await server.cli.execWithEnv(`npm run plugin:install -- --npm-name peertube-theme-background-red`)
})
it('Should have the theme and the plugin registered when we restart peertube', async function () {
this.timeout(30000)
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
- const res = await getConfig(server.url)
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const plugin = config.plugin.registered
.find(p => p.name === 'test')
it('Should uninstall a plugin from stateless CLI', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- await execCLI(`${env} npm run plugin:uninstall -- --npm-name peertube-plugin-test`)
+ await server.cli.execWithEnv(`npm run plugin:uninstall -- --npm-name peertube-plugin-test`)
})
it('Should have removed the plugin on another peertube restart', async function () {
this.timeout(30000)
- killallServers([ server ])
- await reRunServer(server)
+ await killallServers([ server ])
+ await server.run()
- const res = await getConfig(server.url)
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const plugin = config.plugin.registered
.find(p => p.name === 'test')
import 'mocha'
import * as chai from 'chai'
-import { execCLI } from '../../../shared/extra-utils'
+import { getVideoFileBitrate, getVideoFileFPS } from '@server/helpers/ffprobe-utils'
+import { CLICommand } from '@shared/extra-utils'
import { getTargetBitrate, VideoResolution } from '../../../shared/models/videos'
import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants'
-import { getVideoFileBitrate, getVideoFileFPS } from '@server/helpers/ffprobe-utils'
const expect = chai.expect
describe('Test create transcoding jobs', function () {
+
it('Should print the correct command for each resolution', async function () {
const fixturePath = 'server/tests/fixtures/video_short.webm'
const fps = await getVideoFileFPS(fixturePath)
VideoResolution.H_720P,
VideoResolution.H_1080P
]) {
- const command = await execCLI(`npm run print-transcode-command -- ${fixturePath} -r ${resolution}`)
+ const command = await CLICommand.exec(`npm run print-transcode-command -- ${fixturePath} -r ${resolution}`)
const targetBitrate = Math.min(getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS), bitrate)
expect(command).to.includes(`-vf scale=w=-2:h=${resolution}`)
import { createFile, readdir } from 'fs-extra'
import { join } from 'path'
import { buildUUID } from '@server/helpers/uuid'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
import {
- buildServerDirectory,
cleanupTests,
- createVideoPlaylist,
+ CLICommand,
+ createMultipleServers,
doubleFollow,
- execCLI,
- flushAndRunMultipleServers,
- getAccount,
- getEnvCli,
killallServers,
makeGetRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateMyAvatar,
- uploadVideo,
- wait
-} from '../../../shared/extra-utils'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
-import { Account, VideoPlaylistPrivacy } from '../../../shared/models'
+ wait,
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
-async function countFiles (internalServerNumber: number, directory: string) {
- const files = await readdir(buildServerDirectory({ internalServerNumber }, directory))
+async function countFiles (server: PeerTubeServer, directory: string) {
+ const files = await readdir(server.servers.buildDirectory(directory))
return files.length
}
-async function assertNotExists (internalServerNumber: number, directory: string, substring: string) {
- const files = await readdir(buildServerDirectory({ internalServerNumber }, directory))
+async function assertNotExists (server: PeerTubeServer, directory: string, substring: string) {
+ const files = await readdir(server.servers.buildDirectory(directory))
for (const f of files) {
expect(f).to.not.contain(substring)
}
}
-async function assertCountAreOkay (servers: ServerInfo[]) {
+async function assertCountAreOkay (servers: PeerTubeServer[], videoServer2UUID: string) {
for (const server of servers) {
- const videosCount = await countFiles(server.internalServerNumber, 'videos')
+ const videosCount = await countFiles(server, 'videos')
expect(videosCount).to.equal(8)
- const torrentsCount = await countFiles(server.internalServerNumber, 'torrents')
+ const torrentsCount = await countFiles(server, 'torrents')
expect(torrentsCount).to.equal(16)
- const previewsCount = await countFiles(server.internalServerNumber, 'previews')
+ const previewsCount = await countFiles(server, 'previews')
expect(previewsCount).to.equal(2)
- const thumbnailsCount = await countFiles(server.internalServerNumber, 'thumbnails')
+ const thumbnailsCount = await countFiles(server, 'thumbnails')
expect(thumbnailsCount).to.equal(6)
- const avatarsCount = await countFiles(server.internalServerNumber, 'avatars')
+ const avatarsCount = await countFiles(server, 'avatars')
expect(avatarsCount).to.equal(2)
}
+
+ // When we'll prune HLS directories too
+ // const hlsRootCount = await countFiles(servers[1], 'streaming-playlists/hls/')
+ // expect(hlsRootCount).to.equal(2)
+
+ // const hlsCount = await countFiles(servers[1], 'streaming-playlists/hls/' + videoServer2UUID)
+ // expect(hlsCount).to.equal(10)
}
describe('Test prune storage scripts', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
const badNames: { [directory: string]: string[] } = {}
+ let videoServer2UUID: string
+
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: true } })
+ servers = await createMultipleServers(2, { transcoding: { enabled: true } })
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
for (const server of servers) {
- await uploadVideo(server.url, server.accessToken, { name: 'video 1' })
- await uploadVideo(server.url, server.accessToken, { name: 'video 2' })
+ await server.videos.upload({ attributes: { name: 'video 1' } })
- await updateMyAvatar({ url: server.url, accessToken: server.accessToken, fixture: 'avatar.png' })
+ const { uuid } = await server.videos.upload({ attributes: { name: 'video 2' } })
+ if (server.serverNumber === 2) videoServer2UUID = uuid
- await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: {
+ await server.users.updateMyAvatar({ fixture: 'avatar.png' })
+
+ await server.playlists.create({
+ attributes: {
displayName: 'playlist',
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id,
+ videoChannelId: server.store.channel.id,
thumbnailfile: 'thumbnail.jpg'
}
})
// Lazy load the remote avatar
{
- const res = await getAccount(servers[0].url, 'root@localhost:' + servers[1].port)
- const account: Account = res.body
+ const account = await servers[0].accounts.get({ accountName: 'root@localhost:' + servers[1].port })
await makeGetRequest({
url: servers[0].url,
path: account.avatar.path,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
}
{
- const res = await getAccount(servers[1].url, 'root@localhost:' + servers[0].port)
- const account: Account = res.body
+ const account = await servers[1].accounts.get({ accountName: 'root@localhost:' + servers[0].port })
await makeGetRequest({
url: servers[1].url,
path: account.avatar.path,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
}
await wait(1000)
await waitJobs(servers)
- killallServers(servers)
+ await killallServers(servers)
await wait(1000)
})
it('Should have the files on the disk', async function () {
- await assertCountAreOkay(servers)
+ await assertCountAreOkay(servers, videoServer2UUID)
})
it('Should create some dirty files', async function () {
for (let i = 0; i < 2; i++) {
{
- const base = buildServerDirectory(servers[0], 'videos')
+ const base = servers[0].servers.buildDirectory('videos')
const n1 = buildUUID() + '.mp4'
const n2 = buildUUID() + '.webm'
}
{
- const base = buildServerDirectory(servers[0], 'torrents')
+ const base = servers[0].servers.buildDirectory('torrents')
const n1 = buildUUID() + '-240.torrent'
const n2 = buildUUID() + '-480.torrent'
}
{
- const base = buildServerDirectory(servers[0], 'thumbnails')
+ const base = servers[0].servers.buildDirectory('thumbnails')
const n1 = buildUUID() + '.jpg'
const n2 = buildUUID() + '.jpg'
}
{
- const base = buildServerDirectory(servers[0], 'previews')
+ const base = servers[0].servers.buildDirectory('previews')
const n1 = buildUUID() + '.jpg'
const n2 = buildUUID() + '.jpg'
}
{
- const base = buildServerDirectory(servers[0], 'avatars')
+ const base = servers[0].servers.buildDirectory('avatars')
const n1 = buildUUID() + '.png'
const n2 = buildUUID() + '.jpg'
badNames['avatars'] = [ n1, n2 ]
}
+
+ // When we'll prune HLS directories too
+ // {
+ // const directory = join('streaming-playlists', 'hls')
+ // const base = servers[1].servers.buildDirectory(directory)
+
+ // const n1 = buildUUID()
+ // await createFile(join(base, n1))
+ // badNames[directory] = [ n1 ]
+ // }
+
+ // {
+ // const directory = join('streaming-playlists', 'hls', videoServer2UUID)
+ // const base = servers[1].servers.buildDirectory(directory)
+ // const n1 = buildUUID() + '-240-fragmented-.mp4'
+ // const n2 = buildUUID() + '-master.m3u8'
+
+ // await createFile(join(base, n1))
+ // await createFile(join(base, n2))
+
+ // badNames[directory] = [ n1, n2 ]
+ // }
}
})
it('Should run prune storage', async function () {
this.timeout(30000)
- const env = getEnvCli(servers[0])
- await execCLI(`echo y | ${env} npm run prune-storage`)
+ const env = servers[0].cli.getEnv()
+ await CLICommand.exec(`echo y | ${env} npm run prune-storage`)
})
it('Should have removed files', async function () {
- await assertCountAreOkay(servers)
+ await assertCountAreOkay(servers, videoServer2UUID)
for (const directory of Object.keys(badNames)) {
for (const name of badNames[directory]) {
- await assertNotExists(servers[0].internalServerNumber, directory, name)
+ await assertNotExists(servers[0], directory, name)
}
}
})
import { expect } from 'chai'
import { writeFile } from 'fs-extra'
import { basename, join } from 'path'
-import { Video, VideoDetails } from '@shared/models'
+import { HttpStatusCode, Video } from '@shared/models'
import {
- buildServerDirectory,
cleanupTests,
+ createMultipleServers,
doubleFollow,
- execCLI,
- flushAndRunMultipleServers,
- getEnvCli,
- getVideo,
makeRawRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideoAndGetId,
waitJobs
} from '../../../shared/extra-utils'
-import { HttpStatusCode } from '@shared/core-utils'
-async function testThumbnail (server: ServerInfo, videoId: number | string) {
- const res = await getVideo(server.url, videoId)
- const video: VideoDetails = res.body
+async function testThumbnail (server: PeerTubeServer, videoId: number | string) {
+ const video = await server.videos.get({ id: videoId })
- const res1 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200)
- expect(res1.body).to.not.have.lengthOf(0)
+ const requests = [
+ makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200),
+ makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200)
+ ]
- const res2 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200)
- expect(res2.body).to.not.have.lengthOf(0)
+ for (const req of requests) {
+ const res = await req
+ expect(res.body).to.not.have.lengthOf(0)
+ }
}
describe('Test regenerate thumbnails script', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let video1: Video
let video2: Video
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
{
- const videoUUID1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 1' })).uuid
- video1 = await (getVideo(servers[0].url, videoUUID1).then(res => res.body))
+ const videoUUID1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid
+ video1 = await servers[0].videos.get({ id: videoUUID1 })
- thumbnail1Path = join(buildServerDirectory(servers[0], 'thumbnails'), basename(video1.thumbnailPath))
+ thumbnail1Path = join(servers[0].servers.buildDirectory('thumbnails'), basename(video1.thumbnailPath))
- const videoUUID2 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 2' })).uuid
- video2 = await (getVideo(servers[0].url, videoUUID2).then(res => res.body))
+ const videoUUID2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).uuid
+ video2 = await servers[0].videos.get({ id: videoUUID2 })
}
{
- const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3' })).uuid
+ const videoUUID = (await servers[1].videos.quickUpload({ name: 'video 3' })).uuid
await waitJobs(servers)
- remoteVideo = await (getVideo(servers[0].url, videoUUID).then(res => res.body))
+ remoteVideo = await servers[0].videos.get({ id: videoUUID })
- thumbnailRemotePath = join(buildServerDirectory(servers[0], 'thumbnails'), basename(remoteVideo.thumbnailPath))
+ thumbnailRemotePath = join(servers[0].servers.buildDirectory('thumbnails'), basename(remoteVideo.thumbnailPath))
}
await writeFile(thumbnail1Path, '')
it('Should regenerate local thumbnails from the CLI', async function () {
this.timeout(15000)
- const env = getEnvCli(servers[0])
- await execCLI(`${env} npm run regenerate-thumbnails`)
+ await servers[0].cli.execWithEnv(`npm run regenerate-thumbnails`)
})
it('Should have generated new thumbnail files', async function () {
import 'mocha'
-
-import {
- cleanupTests,
- createUser,
- execCLI,
- flushAndRunServer,
- getEnvCli,
- login,
- ServerInfo,
- setAccessTokensToServers
-} from '../../../shared/extra-utils'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { cleanupTests, CLICommand, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '../../../shared/extra-utils'
describe('Test reset password scripts', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'user_1', password: 'super password' })
+ await server.users.create({ username: 'user_1', password: 'super password' })
})
it('Should change the user password from CLI', async function () {
this.timeout(60000)
- const env = getEnvCli(server)
- await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`)
+ const env = server.cli.getEnv()
+ await CLICommand.exec(`echo coucou | ${env} npm run reset-password -- -u user_1`)
- await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, HttpStatusCode.OK_200)
+ await server.login.login({ user: { username: 'user_1', password: 'coucou' } })
})
after(async function () {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import * as chai from 'chai'
-import { VideoDetails } from '../../../shared/models/videos'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
-import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
+import { expect } from 'chai'
import {
- addVideoChannel,
cleanupTests,
- createUser,
- execCLI,
- flushAndRunServer,
- getEnvCli,
- getVideo,
- getVideoChannelsList,
- getVideosList,
+ createSingleServer,
killallServers,
makeActivityPubGetRequest,
- parseTorrentVideo, reRunServer,
- ServerInfo,
+ parseTorrentVideo,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo
-} from '../../../shared/extra-utils'
-import { getAccountsList } from '../../../shared/extra-utils/users/accounts'
-
-const expect = chai.expect
+ waitJobs
+} from '@shared/extra-utils'
describe('Test update host scripts', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(60000)
}
}
// Run server 2 to have transcoding enabled
- server = await flushAndRunServer(2, overrideConfig)
+ server = await createSingleServer(2, overrideConfig)
await setAccessTokensToServers([ server ])
// Upload two videos for our needs
- const videoAttributes = {}
- const resVideo1 = await uploadVideo(server.url, server.accessToken, videoAttributes)
- const video1UUID = resVideo1.body.video.uuid
- await uploadVideo(server.url, server.accessToken, videoAttributes)
+ const { uuid: video1UUID } = await server.videos.upload()
+ await server.videos.upload()
// Create a user
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'toto', password: 'coucou' })
+ await server.users.create({ username: 'toto', password: 'coucou' })
// Create channel
const videoChannel = {
displayName: 'second video channel',
description: 'super video channel description'
}
- await addVideoChannel(server.url, server.accessToken, videoChannel)
+ await server.channels.create({ attributes: videoChannel })
// Create comments
const text = 'my super first comment'
- await addVideoCommentThread(server.url, server.accessToken, video1UUID, text)
+ await server.comments.createThread({ videoId: video1UUID, text })
await waitJobs(server)
})
it('Should run update host', async function () {
this.timeout(30000)
- killallServers([ server ])
+ await killallServers([ server ])
// Run server with standard configuration
- await reRunServer(server)
+ await server.run()
- const env = getEnvCli(server)
- await execCLI(`${env} npm run update-host`)
+ await server.cli.execWithEnv(`npm run update-host`)
})
it('Should have updated videos url', async function () {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(2)
+ const { total, data } = await server.videos.list()
+ expect(total).to.equal(2)
- for (const video of res.body.data) {
+ for (const video of data) {
const { body } = await makeActivityPubGetRequest(server.url, '/videos/watch/' + video.uuid)
expect(body.id).to.equal('http://localhost:9002/videos/watch/' + video.uuid)
- const res = await getVideo(server.url, video.uuid)
- const videoDetails: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: video.uuid })
expect(videoDetails.trackerUrls[0]).to.include(server.host)
expect(videoDetails.streamingPlaylists[0].playlistUrl).to.include(server.host)
})
it('Should have updated video channels url', async function () {
- const res = await getVideoChannelsList(server.url, 0, 5, '-name')
- expect(res.body.total).to.equal(3)
+ const { data, total } = await server.channels.list({ sort: '-name' })
+ expect(total).to.equal(3)
- for (const channel of res.body.data) {
+ for (const channel of data) {
const { body } = await makeActivityPubGetRequest(server.url, '/video-channels/' + channel.name)
expect(body.id).to.equal('http://localhost:9002/video-channels/' + channel.name)
})
it('Should have updated accounts url', async function () {
- const res = await getAccountsList(server.url)
- expect(res.body.total).to.equal(3)
+ const body = await server.accounts.list()
+ expect(body.total).to.equal(3)
- for (const account of res.body.data) {
+ for (const account of body.data) {
const usernameWithDomain = account.name
const { body } = await makeActivityPubGetRequest(server.url, '/accounts/' + usernameWithDomain)
it('Should have updated torrent hosts', async function () {
this.timeout(30000)
- const res = await getVideosList(server.url)
- const videos = res.body.data
- expect(videos).to.have.lengthOf(2)
+ const { data } = await server.videos.list()
+ expect(data).to.have.lengthOf(2)
- for (const video of videos) {
- const res2 = await getVideo(server.url, video.id)
- const videoDetails: VideoDetails = res2.body
+ for (const video of data) {
+ const videoDetails = await server.videos.get({ id: video.id })
+ const files = videoDetails.files.concat(videoDetails.streamingPlaylists[0].files)
- expect(videoDetails.files).to.have.lengthOf(4)
+ expect(files).to.have.lengthOf(8)
- for (const file of videoDetails.files) {
+ for (const file of files) {
expect(file.magnetUri).to.contain('localhost%3A9002%2Ftracker%2Fsocket')
- expect(file.magnetUri).to.contain('localhost%3A9002%2Fstatic%2Fwebseed%2F')
+ expect(file.magnetUri).to.contain('localhost%3A9002%2Fstatic%2F')
- const torrent = await parseTorrentVideo(server, videoDetails.uuid, file.resolution.id)
+ const torrent = await parseTorrentVideo(server, file)
const announceWS = torrent.announce.find(a => a === 'ws://localhost:9002/tracker/socket')
expect(announceWS).to.not.be.undefined
const announceHttp = torrent.announce.find(a => a === 'http://localhost:9002/tracker/announce')
expect(announceHttp).to.not.be.undefined
- expect(torrent.urlList[0]).to.contain('http://localhost:9002/static/webseed')
+ expect(torrent.urlList[0]).to.contain('http://localhost:9002/static/')
}
}
})
import 'mocha'
import * as chai from 'chai'
import { omit } from 'lodash'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import { Account, CustomConfig, HTMLServerConfig, ServerConfig, VideoPlaylistCreateResult, VideoPlaylistPrivacy } from '@shared/models'
+import { Account, HTMLServerConfig, HttpStatusCode, ServerConfig, VideoPlaylistCreateResult, VideoPlaylistPrivacy } from '@shared/models'
import {
- addVideoInPlaylist,
cleanupTests,
- createVideoPlaylist,
+ createMultipleServers,
doubleFollow,
- flushAndRunMultipleServers,
- getAccount,
- getConfig,
- getCustomConfig,
- getVideosList,
makeGetRequest,
makeHTMLRequest,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateCustomConfig,
- updateCustomSubConfig,
- updateMyUser,
- updateVideoChannel,
- uploadVideo,
waitJobs
} from '../../shared/extra-utils'
}
describe('Test a client controllers', function () {
- let servers: ServerInfo[] = []
+ let servers: PeerTubeServer[] = []
let account: Account
const videoName = 'my super name for server 1'
before(async function () {
this.timeout(120000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await updateVideoChannel(servers[0].url, servers[0].accessToken, servers[0].videoChannel.name, { description: channelDescription })
+ await servers[0].channels.update({
+ channelName: servers[0].store.channel.name,
+ attributes: { description: channelDescription }
+ })
// Video
- const videoAttributes = { name: videoName, description: videoDescription }
- await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
+ {
+ const attributes = { name: videoName, description: videoDescription }
+ await servers[0].videos.upload({ attributes })
- const resVideosRequest = await getVideosList(servers[0].url)
- const videos = resVideosRequest.body.data
- expect(videos.length).to.equal(1)
+ const { data } = await servers[0].videos.list()
+ expect(data.length).to.equal(1)
- const video = videos[0]
- servers[0].video = video
- videoIds = [ video.id, video.uuid, video.shortUUID ]
+ const video = data[0]
+ servers[0].store.video = video
+ videoIds = [ video.id, video.uuid, video.shortUUID ]
+ }
// Playlist
- const playlistAttrs = {
- displayName: playlistName,
- description: playlistDescription,
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].videoChannel.id
- }
+ {
+ const attributes = {
+ displayName: playlistName,
+ description: playlistDescription,
+ privacy: VideoPlaylistPrivacy.PUBLIC,
+ videoChannelId: servers[0].store.channel.id
+ }
- const resVideoPlaylistRequest = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs })
- playlist = resVideoPlaylistRequest.body.videoPlaylist
- playlistIds = [ playlist.id, playlist.shortUUID, playlist.uuid ]
+ playlist = await servers[0].playlists.create({ attributes })
+ playlistIds = [ playlist.id, playlist.shortUUID, playlist.uuid ]
- await addVideoInPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistId: playlist.shortUUID,
- elementAttrs: { videoId: video.id }
- })
+ await servers[0].playlists.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: servers[0].store.video.id } })
+ }
// Account
- await updateMyUser({ url: servers[0].url, accessToken: servers[0].accessToken, description: 'my account description' })
+ {
+ await servers[0].users.updateMe({ description: 'my account description' })
- const resAccountRequest = await getAccount(servers[0].url, `${servers[0].user.username}@${servers[0].host}`)
- account = resAccountRequest.body
+ account = await servers[0].accounts.get({ accountName: `${servers[0].store.user.username}@${servers[0].host}` })
+ }
await waitJobs(servers)
})
url: servers[0].url,
path: basePath + id,
accept: 'text/html',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
const port = servers[0].port
const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
- `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2F${servers[0].video.uuid}" ` +
- `title="${servers[0].video.name}" />`
+ `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2F${servers[0].store.video.shortUUID}" ` +
+ `title="${servers[0].store.video.name}" />`
expect(res.text).to.contain(expectedLink)
}
url: servers[0].url,
path: basePath + id,
accept: 'text/html',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
const port = servers[0].port
const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
- `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2Fp%2F${playlist.uuid}" ` +
+ `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2Fp%2F${playlist.shortUUID}" ` +
`title="${playlistName}" />`
expect(res.text).to.contain(expectedLink)
describe('Open Graph', function () {
async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain(`<meta property="og:title" content="${account.displayName}" />`)
expect(text).to.contain(`<meta property="og:description" content="${account.description}" />`)
expect(text).to.contain('<meta property="og:type" content="website" />')
- expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/accounts/${servers[0].user.username}" />`)
+ expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/accounts/${servers[0].store.user.username}" />`)
}
async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
- expect(text).to.contain(`<meta property="og:title" content="${servers[0].videoChannel.displayName}" />`)
+ expect(text).to.contain(`<meta property="og:title" content="${servers[0].store.channel.displayName}" />`)
expect(text).to.contain(`<meta property="og:description" content="${channelDescription}" />`)
expect(text).to.contain('<meta property="og:type" content="website" />')
- expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/video-channels/${servers[0].videoChannel.name}" />`)
+ expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/video-channels/${servers[0].store.channel.name}" />`)
}
async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain(`<meta property="og:title" content="${videoName}" />`)
expect(text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`)
expect(text).to.contain('<meta property="og:type" content="video" />')
- expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/${servers[0].video.uuid}" />`)
+ expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/${servers[0].store.video.shortUUID}" />`)
}
async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain(`<meta property="og:title" content="${playlistName}" />`)
expect(text).to.contain(`<meta property="og:description" content="${playlistDescription}" />`)
expect(text).to.contain('<meta property="og:type" content="video" />')
- expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/p/${playlist.uuid}" />`)
+ expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/p/${playlist.shortUUID}" />`)
}
it('Should have valid Open Graph tags on the account page', async function () {
- await accountPageTest('/accounts/' + servers[0].user.username)
- await accountPageTest('/a/' + servers[0].user.username)
- await accountPageTest('/@' + servers[0].user.username)
+ await accountPageTest('/accounts/' + servers[0].store.user.username)
+ await accountPageTest('/a/' + servers[0].store.user.username)
+ await accountPageTest('/@' + servers[0].store.user.username)
})
it('Should have valid Open Graph tags on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
- await channelPageTest('/c/' + servers[0].videoChannel.name)
- await channelPageTest('/@' + servers[0].videoChannel.name)
+ await channelPageTest('/video-channels/' + servers[0].store.channel.name)
+ await channelPageTest('/c/' + servers[0].store.channel.name)
+ await channelPageTest('/@' + servers[0].store.channel.name)
})
it('Should have valid Open Graph tags on the watch page', async function () {
describe('Not whitelisted', function () {
async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary" />')
}
async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary" />')
expect(text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
- expect(text).to.contain(`<meta property="twitter:title" content="${servers[0].videoChannel.displayName}" />`)
+ expect(text).to.contain(`<meta property="twitter:title" content="${servers[0].store.channel.displayName}" />`)
expect(text).to.contain(`<meta property="twitter:description" content="${channelDescription}" />`)
}
async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
}
async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary" />')
})
it('Should have valid twitter card on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
- await channelPageTest('/c/' + servers[0].videoChannel.name)
- await channelPageTest('/@' + servers[0].videoChannel.name)
+ await channelPageTest('/video-channels/' + servers[0].store.channel.name)
+ await channelPageTest('/c/' + servers[0].store.channel.name)
+ await channelPageTest('/@' + servers[0].store.channel.name)
})
})
describe('Whitelisted', function () {
before(async function () {
- const res = await getCustomConfig(servers[0].url, servers[0].accessToken)
- const config = res.body as CustomConfig
+ const config = await servers[0].config.getCustomConfig()
config.services.twitter = {
username: '@Kuja',
whitelisted: true
}
- await updateCustomConfig(servers[0].url, servers[0].accessToken, config)
+ await servers[0].config.updateCustomConfig({ newCustomConfig: config })
})
async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary" />')
}
async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="summary" />')
}
async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="player" />')
}
async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
+ const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
const text = res.text
expect(text).to.contain('<meta property="twitter:card" content="player" />')
})
it('Should have valid twitter card on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
- await channelPageTest('/c/' + servers[0].videoChannel.name)
- await channelPageTest('/@' + servers[0].videoChannel.name)
+ await channelPageTest('/video-channels/' + servers[0].store.channel.name)
+ await channelPageTest('/c/' + servers[0].store.channel.name)
+ await channelPageTest('/@' + servers[0].store.channel.name)
})
})
})
describe('Index HTML', function () {
it('Should have valid index html tags (title, description...)', async function () {
- const resConfig = await getConfig(servers[0].url)
+ const config = await servers[0].config.getConfig()
const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
- checkIndexTags(res.text, 'PeerTube', description, '', resConfig.body)
+ checkIndexTags(res.text, 'PeerTube', description, '', config)
})
it('Should update the customized configuration and have the correct index html tags', async function () {
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- instance: {
- name: 'PeerTube updated',
- shortDescription: 'my short description',
- description: 'my super description',
- terms: 'my super terms',
- defaultNSFWPolicy: 'blur',
- defaultClientRoute: '/videos/recently-added',
- customizations: {
- javascript: 'alert("coucou")',
- css: 'body { background-color: red; }'
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ instance: {
+ name: 'PeerTube updated',
+ shortDescription: 'my short description',
+ description: 'my super description',
+ terms: 'my super terms',
+ defaultNSFWPolicy: 'blur',
+ defaultClientRoute: '/videos/recently-added',
+ customizations: {
+ javascript: 'alert("coucou")',
+ css: 'body { background-color: red; }'
+ }
}
}
})
- const resConfig = await getConfig(servers[0].url)
+ const config = await servers[0].config.getConfig()
const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
+ checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
})
it('Should have valid index html updated tags (title, description...)', async function () {
- const resConfig = await getConfig(servers[0].url)
+ const config = await servers[0].config.getConfig()
const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
+ checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
})
it('Should use the original video URL for the canonical tag', async function () {
for (const basePath of watchVideoBasePaths) {
for (const id of videoIds) {
const res = await makeHTMLRequest(servers[1].url, basePath + id)
- expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`)
+ expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/videos/watch/${servers[0].store.video.uuid}" />`)
}
}
})
it('Should use the original account URL for the canonical tag', async function () {
- const accountURLtest = (res) => {
+ const accountURLtest = res => {
expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/accounts/root" />`)
}
})
it('Should use the original channel URL for the canonical tag', async function () {
- const channelURLtests = (res) => {
+ const channelURLtests = res => {
expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/video-channels/root_channel" />`)
}
describe('Embed HTML', function () {
it('Should have the correct embed html tags', async function () {
- const resConfig = await getConfig(servers[0].url)
- const res = await makeHTMLRequest(servers[0].url, servers[0].video.embedPath)
+ const config = await servers[0].config.getConfig()
+ const res = await makeHTMLRequest(servers[0].url, servers[0].store.video.embedPath)
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
+ checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
})
})
import 'mocha'
import { expect } from 'chai'
-import { User } from '@shared/models/users/user.model'
-import {
- blockUser,
- getMyUserInformation,
- installPlugin,
- setAccessTokensToServers,
- unblockUser,
- uninstallPlugin,
- updatePluginSettings,
- uploadVideo,
- userLogin
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Official plugin auth-ldap', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let accessToken: string
let userId: number
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-auth-ldap'
- })
+ await server.plugins.install({ npmName: 'peertube-plugin-auth-ldap' })
})
it('Should not login with without LDAP settings', async function () {
- await userLogin(server, { username: 'fry', password: 'fry' }, 400)
+ await server.login.login({ user: { username: 'fry', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not login with bad LDAP settings', async function () {
- await updatePluginSettings({
- url: server.url,
- accessToken: server.accessToken,
+ await server.plugins.updateSettings({
npmName: 'peertube-plugin-auth-ldap',
settings: {
'bind-credentials': 'GoodNewsEveryone',
}
})
- await userLogin(server, { username: 'fry', password: 'fry' }, 400)
+ await server.login.login({ user: { username: 'fry', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not login with good LDAP settings but wrong username/password', async function () {
- await updatePluginSettings({
- url: server.url,
- accessToken: server.accessToken,
+ await server.plugins.updateSettings({
npmName: 'peertube-plugin-auth-ldap',
settings: {
'bind-credentials': 'GoodNewsEveryone',
}
})
- await userLogin(server, { username: 'fry', password: 'bad password' }, 400)
- await userLogin(server, { username: 'fryr', password: 'fry' }, 400)
+ await server.login.login({ user: { username: 'fry', password: 'bad password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.login.login({ user: { username: 'fryr', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should login with the appropriate username/password', async function () {
- accessToken = await userLogin(server, { username: 'fry', password: 'fry' })
+ accessToken = await server.login.getAccessToken({ username: 'fry', password: 'fry' })
})
it('Should login with the appropriate email/password', async function () {
- accessToken = await userLogin(server, { username: 'fry@planetexpress.com', password: 'fry' })
+ accessToken = await server.login.getAccessToken({ username: 'fry@planetexpress.com', password: 'fry' })
})
it('Should login get my profile', async function () {
- const res = await getMyUserInformation(server.url, accessToken)
- const body: User = res.body
-
+ const body = await server.users.getMyInfo({ token: accessToken })
expect(body.username).to.equal('fry')
expect(body.email).to.equal('fry@planetexpress.com')
})
it('Should upload a video', async function () {
- await uploadVideo(server.url, accessToken, { name: 'my super video' })
+ await server.videos.upload({ token: accessToken, attributes: { name: 'my super video' } })
})
it('Should not be able to login if the user is banned', async function () {
- await blockUser(server.url, userId, server.accessToken)
+ await server.users.banUser({ userId })
- await userLogin(server, { username: 'fry@planetexpress.com', password: 'fry' }, 400)
+ await server.login.login({
+ user: { username: 'fry@planetexpress.com', password: 'fry' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
+ })
})
it('Should be able to login if the user is unbanned', async function () {
- await unblockUser(server.url, userId, server.accessToken)
+ await server.users.unbanUser({ userId })
- await userLogin(server, { username: 'fry@planetexpress.com', password: 'fry' })
+ await server.login.login({ user: { username: 'fry@planetexpress.com', password: 'fry' } })
})
it('Should not login if the plugin is uninstalled', async function () {
- await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-auth-ldap' })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-auth-ldap' })
- await userLogin(server, { username: 'fry@planetexpress.com', password: 'fry' }, 400)
+ await server.login.login({
+ user: { username: 'fry@planetexpress.com', password: 'fry' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
+ })
})
after(async function () {
import 'mocha'
import { expect } from 'chai'
-import { Video, VideoBlacklist } from '@shared/models'
import {
+ cleanupTests,
+ createMultipleServers,
doubleFollow,
- getBlacklistedVideosList,
- getVideosList,
- installPlugin,
+ killallServers,
MockBlocklist,
- removeVideoFromBlacklist,
+ PeerTubeServer,
setAccessTokensToServers,
- updatePluginSettings,
- uploadVideoAndGetId,
wait
-} from '../../../shared/extra-utils'
-import {
- cleanupTests,
- flushAndRunMultipleServers,
- killallServers,
- reRunServer,
- ServerInfo
-} from '../../../shared/extra-utils/server/servers'
+} from '@shared/extra-utils'
+import { Video } from '@shared/models'
-async function check (server: ServerInfo, videoUUID: string, exists = true) {
- const res = await getVideosList(server.url)
+async function check (server: PeerTubeServer, videoUUID: string, exists = true) {
+ const { data } = await server.videos.list()
- const video = res.body.data.find(v => v.uuid === videoUUID)
+ const video = data.find(v => v.uuid === videoUUID)
- if (exists) {
- expect(video).to.not.be.undefined
- } else {
- expect(video).to.be.undefined
- }
+ if (exists) expect(video).to.not.be.undefined
+ else expect(video).to.be.undefined
}
describe('Official plugin auto-block videos', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let blocklistServer: MockBlocklist
let server1Videos: Video[] = []
let server2Videos: Video[] = []
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
for (const server of servers) {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-auto-block-videos'
- })
+ await server.plugins.install({ npmName: 'peertube-plugin-auto-block-videos' })
}
blocklistServer = new MockBlocklist()
port = await blocklistServer.initialize()
- await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })
- await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })
- await uploadVideoAndGetId({ server: servers[1], videoName: 'video 2 server 2' })
- await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3 server 2' })
+ await servers[0].videos.quickUpload({ name: 'video server 1' })
+ await servers[1].videos.quickUpload({ name: 'video server 2' })
+ await servers[1].videos.quickUpload({ name: 'video 2 server 2' })
+ await servers[1].videos.quickUpload({ name: 'video 3 server 2' })
{
- const res = await getVideosList(servers[0].url)
- server1Videos = res.body.data.map(v => Object.assign(v, { url: servers[0].url + '/videos/watch/' + v.uuid }))
+ const { data } = await servers[0].videos.list()
+ server1Videos = data.map(v => Object.assign(v, { url: servers[0].url + '/videos/watch/' + v.uuid }))
}
{
- const res = await getVideosList(servers[1].url)
- server2Videos = res.body.data.map(v => Object.assign(v, { url: servers[1].url + '/videos/watch/' + v.uuid }))
+ const { data } = await servers[1].videos.list()
+ server2Videos = data.map(v => Object.assign(v, { url: servers[1].url + '/videos/watch/' + v.uuid }))
}
await doubleFollow(servers[0], servers[1])
})
it('Should update plugin settings', async function () {
- await updatePluginSettings({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].plugins.updateSettings({
npmName: 'peertube-plugin-auto-block-videos',
settings: {
'blocklist-urls': `http://localhost:${port}/blocklist`,
})
it('Should have video in blacklists', async function () {
- const res = await getBlacklistedVideosList({ url: servers[0].url, token: servers[0].accessToken })
-
- const videoBlacklists = res.body.data as VideoBlacklist[]
+ const body = await servers[0].blacklist.list()
+ const videoBlacklists = body.data
expect(videoBlacklists).to.have.lengthOf(1)
expect(videoBlacklists[0].reason).to.contains('Automatically blocked from auto block plugin')
expect(videoBlacklists[0].video.name).to.equal(server2Videos[0].name)
await check(servers[0], video.uuid, false)
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, video.uuid)
+ await servers[0].blacklist.remove({ videoId: video.uuid })
await check(servers[0], video.uuid, true)
- killallServers([ servers[0] ])
- await reRunServer(servers[0])
+ await killallServers([ servers[0] ])
+ await servers[0].run()
await wait(2000)
await check(servers[0], video.uuid, true)
import 'mocha'
import { expect } from 'chai'
import {
- addAccountToServerBlocklist,
- addServerToAccountBlocklist,
- removeAccountFromServerBlocklist
-} from '@shared/extra-utils/users/blocklist'
-import {
+ cleanupTests,
+ createMultipleServers,
doubleFollow,
- getVideosList,
- installPlugin,
+ killallServers,
makeGetRequest,
MockBlocklist,
+ PeerTubeServer,
setAccessTokensToServers,
- updatePluginSettings,
- uploadVideoAndGetId,
wait
-} from '../../../shared/extra-utils'
-import {
- cleanupTests,
- flushAndRunMultipleServers,
- killallServers,
- reRunServer,
- ServerInfo
-} from '../../../shared/extra-utils/server/servers'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Official plugin auto-mute', function () {
const autoMuteListPath = '/plugins/auto-mute/router/api/v1/mute-list'
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let blocklistServer: MockBlocklist
let port: number
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
for (const server of servers) {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-auto-mute'
- })
+ await server.plugins.install({ npmName: 'peertube-plugin-auto-mute' })
}
blocklistServer = new MockBlocklist()
port = await blocklistServer.initialize()
- await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })
- await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })
+ await servers[0].videos.quickUpload({ name: 'video server 1' })
+ await servers[1].videos.quickUpload({ name: 'video server 2' })
await doubleFollow(servers[0], servers[1])
})
it('Should update plugin settings', async function () {
- await updatePluginSettings({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].plugins.updateSettings({
npmName: 'peertube-plugin-auto-mute',
settings: {
'blocklist-urls': `http://localhost:${port}/blocklist`,
await wait(2000)
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(1)
})
it('Should remove a server blocklist', async function () {
await wait(2000)
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(2)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(2)
})
it('Should add an account blocklist', async function () {
await wait(2000)
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(1)
})
it('Should remove an account blocklist', async function () {
await wait(2000)
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(2)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(2)
})
it('Should auto mute an account, manually unmute it and do not remute it automatically', async function () {
await wait(2000)
{
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(1)
}
- await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, account)
+ await servers[0].blocklist.removeFromServerBlocklist({ account })
{
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(2)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(2)
}
- killallServers([ servers[0] ])
- await reRunServer(servers[0])
+ await killallServers([ servers[0] ])
+ await servers[0].run()
await wait(2000)
{
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(2)
+ const { total } = await servers[0].videos.list()
+ expect(total).to.equal(2)
}
})
await makeGetRequest({
url: servers[0].url,
path: '/plugins/auto-mute/router/api/v1/mute-list',
- statusCodeExpected: HttpStatusCode.FORBIDDEN_403
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should enable auto mute list', async function () {
- await updatePluginSettings({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
+ await servers[0].plugins.updateSettings({
npmName: 'peertube-plugin-auto-mute',
settings: {
'blocklist-urls': '',
await makeGetRequest({
url: servers[0].url,
path: '/plugins/auto-mute/router/api/v1/mute-list',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
})
it('Should mute an account on server 1, and server 2 auto mutes it', async function () {
this.timeout(20000)
- await updatePluginSettings({
- url: servers[1].url,
- accessToken: servers[1].accessToken,
+ await servers[1].plugins.updateSettings({
npmName: 'peertube-plugin-auto-mute',
settings: {
'blocklist-urls': 'http://localhost:' + servers[0].port + autoMuteListPath,
}
})
- await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'root@localhost:' + servers[1].port)
- await addServerToAccountBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
+ await servers[0].blocklist.addToServerBlocklist({ account: 'root@localhost:' + servers[1].port })
+ await servers[0].blocklist.addToMyBlocklist({ server: 'localhost:' + servers[1].port })
const res = await makeGetRequest({
url: servers[0].url,
path: '/plugins/auto-mute/router/api/v1/mute-list',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
const data = res.body.data
await wait(2000)
for (const server of servers) {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(1)
+ const { total } = await server.videos.list()
+ expect(total).to.equal(1)
}
})
import 'mocha'
import * as chai from 'chai'
import * as xmlParser from 'fast-xml-parser'
-import {
- addAccountToAccountBlocklist,
- addAccountToServerBlocklist,
- removeAccountFromServerBlocklist
-} from '@shared/extra-utils/users/blocklist'
-import { addUserSubscription, listUserSubscriptionVideos } from '@shared/extra-utils/users/user-subscriptions'
-import { VideoPrivacy } from '@shared/models'
-import { ScopedToken } from '@shared/models/users/user-scoped-token'
import {
cleanupTests,
- createUser,
+ createMultipleServers,
+ createSingleServer,
doubleFollow,
- flushAndRunMultipleServers,
- flushAndRunServer,
- getJSONfeed,
- getMyUserInformation,
- getUserScopedTokens,
- getXMLfeed,
- renewUserScopedTokens,
- ServerInfo,
+ makeGetRequest,
+ PeerTubeServer,
setAccessTokensToServers,
- uploadVideo,
- uploadVideoAndGetId,
- userLogin
-} from '../../../shared/extra-utils'
-import { waitJobs } from '../../../shared/extra-utils/server/jobs'
-import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
-import { User } from '../../../shared/models/users'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
chai.use(require('chai-xml'))
chai.use(require('chai-json-schema'))
const expect = chai.expect
describe('Test syndication feeds', () => {
- let servers: ServerInfo[] = []
- let serverHLSOnly: ServerInfo
+ let servers: PeerTubeServer[] = []
+ let serverHLSOnly: PeerTubeServer
let userAccessToken: string
let rootAccountId: number
let rootChannelId: number
this.timeout(120000)
// Run servers
- servers = await flushAndRunMultipleServers(2)
- serverHLSOnly = await flushAndRunServer(3, {
+ servers = await createMultipleServers(2)
+ serverHLSOnly = await createSingleServer(3, {
transcoding: {
enabled: true,
webtorrent: { enabled: false },
await doubleFollow(servers[0], servers[1])
{
- const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- const user: User = res.body
+ const user = await servers[0].users.getMyInfo()
rootAccountId = user.account.id
rootChannelId = user.videoChannels[0].id
}
{
- const attr = { username: 'john', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: attr.username, password: attr.password })
- userAccessToken = await userLogin(servers[0], attr)
+ userAccessToken = await servers[0].users.generateUserAndToken('john')
- const res = await getMyUserInformation(servers[0].url, userAccessToken)
- const user: User = res.body
+ const user = await servers[0].users.getMyInfo({ token: userAccessToken })
userAccountId = user.account.id
userChannelId = user.videoChannels[0].id
- const res2 = await getUserScopedTokens(servers[0].url, userAccessToken)
- const token: ScopedToken = res2.body
+ const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken })
userFeedToken = token.feedToken
}
{
- await uploadVideo(servers[0].url, userAccessToken, { name: 'user video' })
+ await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'user video' } })
}
{
- const videoAttributes = {
+ const attributes = {
name: 'my super name for server 1',
description: 'my super description for server 1',
fixture: 'video_short.webm'
}
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- const videoId = res.body.video.id
+ const { id } = await servers[0].videos.upload({ attributes })
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoId, 'super comment 1')
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoId, 'super comment 2')
+ await servers[0].comments.createThread({ videoId: id, text: 'super comment 1' })
+ await servers[0].comments.createThread({ videoId: id, text: 'super comment 2' })
}
{
- const videoAttributes = { name: 'unlisted video', privacy: VideoPrivacy.UNLISTED }
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- const videoId = res.body.video.id
+ const attributes = { name: 'unlisted video', privacy: VideoPrivacy.UNLISTED }
+ const { id } = await servers[0].videos.upload({ attributes })
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoId, 'comment on unlisted video')
+ await servers[0].comments.createThread({ videoId: id, text: 'comment on unlisted video' })
}
await waitJobs(servers)
it('Should be well formed XML (covers RSS 2.0 and ATOM 1.0 endpoints)', async function () {
for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
- const rss = await getXMLfeed(servers[0].url, feed)
- expect(rss.text).xml.to.be.valid()
+ const rss = await servers[0].feed.getXML({ feed })
+ expect(rss).xml.to.be.valid()
- const atom = await getXMLfeed(servers[0].url, feed, 'atom')
- expect(atom.text).xml.to.be.valid()
+ const atom = await servers[0].feed.getXML({ feed, format: 'atom' })
+ expect(atom).xml.to.be.valid()
}
})
it('Should be well formed JSON (covers JSON feed 1.0 endpoint)', async function () {
for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
- const json = await getJSONfeed(servers[0].url, feed)
- expect(JSON.parse(json.text)).to.be.jsonSchema({ type: 'object' })
+ const jsonText = await servers[0].feed.getJSON({ feed })
+ expect(JSON.parse(jsonText)).to.be.jsonSchema({ type: 'object' })
}
})
+
+ it('Should serve the endpoint with a classic request', async function () {
+ await makeGetRequest({
+ url: servers[0].url,
+ path: '/feeds/videos.xml',
+ accept: 'application/xml',
+ expectedStatus: HttpStatusCode.OK_200
+ })
+ })
+
+ it('Should serve the endpoint as a cached request', async function () {
+ const res = await makeGetRequest({
+ url: servers[0].url,
+ path: '/feeds/videos.xml',
+ accept: 'application/xml',
+ expectedStatus: HttpStatusCode.OK_200
+ })
+
+ expect(res.headers['x-api-cache-cached']).to.equal('true')
+ })
+
+ it('Should not serve the endpoint as a cached request', async function () {
+ const res = await makeGetRequest({
+ url: servers[0].url,
+ path: '/feeds/videos.xml?v=186',
+ accept: 'application/xml',
+ expectedStatus: HttpStatusCode.OK_200
+ })
+
+ expect(res.headers['x-api-cache-cached']).to.not.exist
+ })
+
+ it('Should refuse to serve the endpoint without accept header', async function () {
+ await makeGetRequest({ url: servers[0].url, path: '/feeds/videos.xml', expectedStatus: HttpStatusCode.NOT_ACCEPTABLE_406 })
+ })
})
describe('Videos feed', function () {
it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () {
for (const server of servers) {
- const rss = await getXMLfeed(server.url, 'videos')
- expect(xmlParser.validate(rss.text)).to.be.true
+ const rss = await server.feed.getXML({ feed: 'videos' })
+ expect(xmlParser.validate(rss)).to.be.true
- const xmlDoc = xmlParser.parse(rss.text, { parseAttributeValue: true, ignoreAttributes: false })
+ const xmlDoc = xmlParser.parse(rss, { parseAttributeValue: true, ignoreAttributes: false })
const enclosure = xmlDoc.rss.channel.item[0].enclosure
expect(enclosure).to.exist
it('Should contain a valid \'attachments\' object (covers JSON feed 1.0 endpoint)', async function () {
for (const server of servers) {
- const json = await getJSONfeed(server.url, 'videos')
- const jsonObj = JSON.parse(json.text)
+ const json = await server.feed.getJSON({ feed: 'videos' })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(2)
expect(jsonObj.items[0].attachments).to.exist
expect(jsonObj.items[0].attachments.length).to.be.eq(1)
it('Should filter by account', async function () {
{
- const json = await getJSONfeed(servers[0].url, 'videos', { accountId: rootAccountId })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: rootAccountId } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('my super name for server 1')
expect(jsonObj.items[0].author.name).to.equal('root')
}
{
- const json = await getJSONfeed(servers[0].url, 'videos', { accountId: userAccountId })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: userAccountId } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('user video')
expect(jsonObj.items[0].author.name).to.equal('john')
for (const server of servers) {
{
- const json = await getJSONfeed(server.url, 'videos', { accountName: 'root@localhost:' + servers[0].port })
- const jsonObj = JSON.parse(json.text)
+ const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'root@localhost:' + servers[0].port } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('my super name for server 1')
}
{
- const json = await getJSONfeed(server.url, 'videos', { accountName: 'john@localhost:' + servers[0].port })
- const jsonObj = JSON.parse(json.text)
+ const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'john@localhost:' + servers[0].port } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('user video')
}
it('Should filter by video channel', async function () {
{
- const json = await getJSONfeed(servers[0].url, 'videos', { videoChannelId: rootChannelId })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: rootChannelId } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('my super name for server 1')
expect(jsonObj.items[0].author.name).to.equal('root')
}
{
- const json = await getJSONfeed(servers[0].url, 'videos', { videoChannelId: userChannelId })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: userChannelId } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('user video')
expect(jsonObj.items[0].author.name).to.equal('john')
for (const server of servers) {
{
- const json = await getJSONfeed(server.url, 'videos', { videoChannelName: 'root_channel@localhost:' + servers[0].port })
- const jsonObj = JSON.parse(json.text)
+ const query = { videoChannelName: 'root_channel@localhost:' + servers[0].port }
+ const json = await server.feed.getJSON({ feed: 'videos', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('my super name for server 1')
}
{
- const json = await getJSONfeed(server.url, 'videos', { videoChannelName: 'john_channel@localhost:' + servers[0].port })
- const jsonObj = JSON.parse(json.text)
+ const query = { videoChannelName: 'john_channel@localhost:' + servers[0].port }
+ const json = await server.feed.getJSON({ feed: 'videos', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].title).to.equal('user video')
}
it('Should correctly have videos feed with HLS only', async function () {
this.timeout(120000)
- await uploadVideo(serverHLSOnly.url, serverHLSOnly.accessToken, { name: 'hls only video' })
+ await serverHLSOnly.videos.upload({ attributes: { name: 'hls only video' } })
await waitJobs([ serverHLSOnly ])
- const json = await getJSONfeed(serverHLSOnly.url, 'videos')
- const jsonObj = JSON.parse(json.text)
+ const json = await serverHLSOnly.feed.getJSON({ feed: 'videos' })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1)
expect(jsonObj.items[0].attachments).to.exist
expect(jsonObj.items[0].attachments.length).to.be.eq(4)
it('Should contain valid comments (covers JSON feed 1.0 endpoint) and not from unlisted videos', async function () {
for (const server of servers) {
- const json = await getJSONfeed(server.url, 'video-comments')
+ const json = await server.feed.getJSON({ feed: 'video-comments' })
- const jsonObj = JSON.parse(json.text)
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(2)
expect(jsonObj.items[0].html_content).to.equal('super comment 2')
expect(jsonObj.items[1].html_content).to.equal('super comment 1')
const remoteHandle = 'root@localhost:' + servers[0].port
- await addAccountToServerBlocklist(servers[1].url, servers[1].accessToken, remoteHandle)
+ await servers[1].blocklist.addToServerBlocklist({ account: remoteHandle })
{
- const json = await getJSONfeed(servers[1].url, 'video-comments', { version: 2 })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 2 } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(0)
}
- await removeAccountFromServerBlocklist(servers[1].url, servers[1].accessToken, remoteHandle)
+ await servers[1].blocklist.removeFromServerBlocklist({ account: remoteHandle })
{
- const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'server 2' })).uuid
+ const videoUUID = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
await waitJobs(servers)
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'super comment')
+ await servers[0].comments.createThread({ videoId: videoUUID, text: 'super comment' })
await waitJobs(servers)
- const json = await getJSONfeed(servers[1].url, 'video-comments', { version: 3 })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 3 } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(3)
}
- await addAccountToAccountBlocklist(servers[1].url, servers[1].accessToken, remoteHandle)
+ await servers[1].blocklist.addToMyBlocklist({ account: remoteHandle })
{
- const json = await getJSONfeed(servers[1].url, 'video-comments', { version: 4 })
- const jsonObj = JSON.parse(json.text)
+ const json = await servers[1].feed.getJSON({ feed: 'video-comments', query: { version: 4 } })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(2)
}
})
it('Should list no videos for a user with no videos and no subscriptions', async function () {
const attr = { username: 'feeduser', password: 'password' }
- await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: attr.username, password: attr.password })
- const feeduserAccessToken = await userLogin(servers[0], attr)
+ await servers[0].users.create({ username: attr.username, password: attr.password })
+ const feeduserAccessToken = await servers[0].login.getAccessToken(attr)
{
- const res = await getMyUserInformation(servers[0].url, feeduserAccessToken)
- const user: User = res.body
+ const user = await servers[0].users.getMyInfo({ token: feeduserAccessToken })
feeduserAccountId = user.account.id
}
{
- const res = await getUserScopedTokens(servers[0].url, feeduserAccessToken)
- const token: ScopedToken = res.body
+ const token = await servers[0].users.getMyScopedTokens({ token: feeduserAccessToken })
feeduserFeedToken = token.feedToken
}
{
- const res = await listUserSubscriptionVideos(servers[0].url, feeduserAccessToken)
- expect(res.body.total).to.equal(0)
+ const body = await servers[0].subscriptions.listVideos({ token: feeduserAccessToken })
+ expect(body.total).to.equal(0)
- const json = await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: feeduserFeedToken })
- const jsonObj = JSON.parse(json.text)
+ const query = { accountId: feeduserAccountId, token: feeduserFeedToken }
+ const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
}
})
it('Should fail with an invalid token', async function () {
- await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, HttpStatusCode.FORBIDDEN_403)
+ const query = { accountId: feeduserAccountId, token: 'toto' }
+ await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should fail with a token of another user', async function () {
- await getJSONfeed(
- servers[0].url,
- 'subscriptions',
- { accountId: feeduserAccountId, token: userFeedToken },
- HttpStatusCode.FORBIDDEN_403
- )
+ const query = { accountId: feeduserAccountId, token: userFeedToken }
+ await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should list no videos for a user with videos but no subscriptions', async function () {
- const res = await listUserSubscriptionVideos(servers[0].url, userAccessToken)
- expect(res.body.total).to.equal(0)
+ const body = await servers[0].subscriptions.listVideos({ token: userAccessToken })
+ expect(body.total).to.equal(0)
- const json = await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken })
- const jsonObj = JSON.parse(json.text)
+ const query = { accountId: userAccountId, token: userFeedToken }
+ const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
})
it('Should list self videos for a user with a subscription to themselves', async function () {
this.timeout(30000)
- await addUserSubscription(servers[0].url, userAccessToken, 'john_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'john_channel@localhost:' + servers[0].port })
await waitJobs(servers)
{
- const res = await listUserSubscriptionVideos(servers[0].url, userAccessToken)
- expect(res.body.total).to.equal(1)
- expect(res.body.data[0].name).to.equal('user video')
+ const body = await servers[0].subscriptions.listVideos({ token: userAccessToken })
+ expect(body.total).to.equal(1)
+ expect(body.data[0].name).to.equal('user video')
- const json = await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 1 })
- const jsonObj = JSON.parse(json.text)
+ const query = { accountId: userAccountId, token: userFeedToken, version: 1 }
+ const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(1) // subscribed to self, it should not list the instance's videos but list john's
}
})
it('Should list videos of a user\'s subscription', async function () {
this.timeout(30000)
- await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:' + servers[0].port)
+ await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@localhost:' + servers[0].port })
await waitJobs(servers)
{
- const res = await listUserSubscriptionVideos(servers[0].url, userAccessToken)
- expect(res.body.total).to.equal(2, "there should be 2 videos part of the subscription")
+ const body = await servers[0].subscriptions.listVideos({ token: userAccessToken })
+ expect(body.total).to.equal(2, "there should be 2 videos part of the subscription")
- const json = await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 2 })
- const jsonObj = JSON.parse(json.text)
+ const query = { accountId: userAccountId, token: userFeedToken, version: 2 }
+ const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query })
+ const jsonObj = JSON.parse(json)
expect(jsonObj.items.length).to.be.equal(2) // subscribed to root, it should not list the instance's videos but list root/john's
}
})
it('Should renew the token, and so have an invalid old token', async function () {
- await renewUserScopedTokens(servers[0].url, userAccessToken)
-
- await getJSONfeed(
- servers[0].url,
- 'subscriptions',
- { accountId: userAccountId, token: userFeedToken, version: 3 },
- HttpStatusCode.FORBIDDEN_403
- )
+ await servers[0].users.renewMyScopedTokens({ token: userAccessToken })
+
+ const query = { accountId: userAccountId, token: userFeedToken, version: 3 }
+ await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should succeed with the new token', async function () {
- const res2 = await getUserScopedTokens(servers[0].url, userAccessToken)
- const token: ScopedToken = res2.body
+ const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken })
userFeedToken = token.feedToken
- await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 4 })
+ const query = { accountId: userAccountId, token: userFeedToken, version: 4 }
+ await servers[0].feed.getJSON({ feed: 'subscriptions', query })
})
})
const builder = (options) => {
return {
outputOptions: [
- '-r:' + options.streamNum + ' 5'
+ '-r:' + options.streamNum + ' 50'
]
}
}
- transcodingManager.addLiveProfile('libx264', 'low-live', builder)
+ transcodingManager.addLiveProfile('libx264', 'high-live', builder)
}
}
const builder = () => {
return {
inputOptions: [
- '-r 5'
+ '-r 50'
]
}
}
}
}
-
async function unregister () {
return
}
async function register ({
- registerHook,
- registerSetting,
- settingsManager,
- storageManager,
videoCategoryManager,
videoLicenceManager,
videoLanguageManager,
videoPrivacyManager,
- playlistPrivacyManager
+ playlistPrivacyManager,
+ getRouter
}) {
- videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
+ videoLanguageManager.addConstant('al_bhed', 'Al Bhed')
videoLanguageManager.addLanguage('al_bhed2', 'Al Bhed 2')
- videoLanguageManager.addLanguage('al_bhed3', 'Al Bhed 3')
- videoLanguageManager.deleteLanguage('en')
+ videoLanguageManager.addConstant('al_bhed3', 'Al Bhed 3')
+ videoLanguageManager.deleteConstant('en')
videoLanguageManager.deleteLanguage('fr')
- videoLanguageManager.deleteLanguage('al_bhed3')
+ videoLanguageManager.deleteConstant('al_bhed3')
videoCategoryManager.addCategory(42, 'Best category')
- videoCategoryManager.addCategory(43, 'High best category')
- videoCategoryManager.deleteCategory(1) // Music
+ videoCategoryManager.addConstant(43, 'High best category')
+ videoCategoryManager.deleteConstant(1) // Music
videoCategoryManager.deleteCategory(2) // Films
videoLicenceManager.addLicence(42, 'Best licence')
- videoLicenceManager.addLicence(43, 'High best licence')
- videoLicenceManager.deleteLicence(1) // Attribution
- videoLicenceManager.deleteLicence(7) // Public domain
+ videoLicenceManager.addConstant(43, 'High best licence')
+ videoLicenceManager.deleteConstant(1) // Attribution
+ videoLicenceManager.deleteConstant(7) // Public domain
+ videoPrivacyManager.deleteConstant(2)
videoPrivacyManager.deletePrivacy(2)
+ playlistPrivacyManager.deleteConstant(3)
playlistPrivacyManager.deletePlaylistPrivacy(3)
-}
-async function unregister () {
- return
+ {
+ const router = getRouter()
+ router.get('/reset-categories', (req, res) => {
+ videoCategoryManager.resetConstants()
+
+ res.sendStatus(204)
+ })
+ }
}
+async function unregister () {}
+
module.exports = {
register,
unregister
}
-
-// ############################################################################
-
-function addToCount (obj) {
- return Object.assign({}, obj, { count: obj.count + 1 })
-}
})
{
- const searchHooks = [
+ const filterHooks = [
'filter:api.search.videos.local.list.params',
'filter:api.search.videos.local.list.result',
'filter:api.search.videos.index.list.params',
'filter:api.search.video-playlists.local.list.params',
'filter:api.search.video-playlists.local.list.result',
'filter:api.search.video-playlists.index.list.params',
- 'filter:api.search.video-playlists.index.list.result'
+ 'filter:api.search.video-playlists.index.list.result',
+
+ 'filter:api.overviews.videos.list.params',
+ 'filter:api.overviews.videos.list.result'
]
- for (const h of searchHooks) {
+ for (const h of filterHooks) {
registerHook({
target: h,
handler: (obj) => {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import { VideoCommentModel } from '../../models/video/video-comment'
const expect = chai.expect
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
+import * as chai from 'chai'
import { snakeCase } from 'lodash'
-import { objectConverter, parseBytes } from '../../helpers/core-utils'
import validator from 'validator'
+import { objectConverter, parseBytes } from '../../helpers/core-utils'
const expect = chai.expect
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
+import { expect } from 'chai'
import { readFile, remove } from 'fs-extra'
import { join } from 'path'
import { processImage } from '../../../server/helpers/image-utils'
import { buildAbsoluteFixturePath, root } from '../../../shared/extra-utils'
-import { expect } from 'chai'
async function checkBuffers (path1: string, path2: string, equals: boolean) {
const [ buf1, buf2 ] = await Promise.all([
import { expect } from 'chai'
import { pathExists, remove } from 'fs-extra'
import { join } from 'path'
-import { get4KFileUrl, root, wait } from '../../../shared/extra-utils'
+import { FIXTURE_URLS, root, wait } from '../../../shared/extra-utils'
import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
describe('Request helpers', function () {
it('Should throw an error when the bytes limit is exceeded for request', async function () {
try {
- await doRequest(get4KFileUrl(), { bodyKBLimit: 3 })
+ await doRequest(FIXTURE_URLS.video4K, { bodyKBLimit: 3 })
} catch {
return
}
it('Should throw an error when the bytes limit is exceeded for request and save file', async function () {
try {
- await doRequestAndSaveToFile(get4KFileUrl(), destPath1, { bodyKBLimit: 3 })
+ await doRequestAndSaveToFile(FIXTURE_URLS.video4K, destPath1, { bodyKBLimit: 3 })
} catch {
await wait(500)
})
it('Should succeed if the file is below the limit', async function () {
- await doRequest(get4KFileUrl(), { bodyKBLimit: 5 })
- await doRequestAndSaveToFile(get4KFileUrl(), destPath2, { bodyKBLimit: 5 })
+ await doRequest(FIXTURE_URLS.video4K, { bodyKBLimit: 5 })
+ await doRequestAndSaveToFile(FIXTURE_URLS.video4K, destPath2, { bodyKBLimit: 5 })
expect(await pathExists(destPath2)).to.be.true
})
import './api/'
import './plugins/'
import './helpers/'
+import './lib/'
--- /dev/null
+export * from './video-constant-registry-factory'
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+import 'mocha'
+import { expect } from 'chai'
+import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
+import {
+ VIDEO_CATEGORIES,
+ VIDEO_LANGUAGES,
+ VIDEO_LICENCES,
+ VIDEO_PLAYLIST_PRIVACIES,
+ VIDEO_PRIVACIES
+} from '@server/initializers/constants'
+import {
+ VideoPlaylistPrivacy,
+ VideoPrivacy
+} from '@shared/models'
+
+describe('VideoConstantManagerFactory', function () {
+ const factory = new VideoConstantManagerFactory('peertube-plugin-constants')
+
+ afterEach(() => {
+ factory.resetVideoConstants('peertube-plugin-constants')
+ })
+
+ describe('VideoCategoryManager', () => {
+ const videoCategoryManager = factory.createVideoConstantManager<number>('category')
+
+ it('Should be able to list all video category constants', () => {
+ const constants = videoCategoryManager.getConstants()
+ expect(constants).to.deep.equal(VIDEO_CATEGORIES)
+ })
+
+ it('Should be able to delete a video category constant', () => {
+ const successfullyDeleted = videoCategoryManager.deleteConstant(1)
+ expect(successfullyDeleted).to.be.true
+ expect(videoCategoryManager.getConstantValue(1)).to.be.undefined
+ })
+
+ it('Should be able to add a video category constant', () => {
+ const successfullyAdded = videoCategoryManager.addConstant(42, 'The meaning of life')
+ expect(successfullyAdded).to.be.true
+ expect(videoCategoryManager.getConstantValue(42)).to.equal('The meaning of life')
+ })
+
+ it('Should be able to reset video category constants', () => {
+ videoCategoryManager.deleteConstant(1)
+ videoCategoryManager.resetConstants()
+ expect(videoCategoryManager.getConstantValue(1)).not.be.undefined
+ })
+ })
+
+ describe('VideoLicenceManager', () => {
+ const videoLicenceManager = factory.createVideoConstantManager<number>('licence')
+ it('Should be able to list all video licence constants', () => {
+ const constants = videoLicenceManager.getConstants()
+ expect(constants).to.deep.equal(VIDEO_LICENCES)
+ })
+
+ it('Should be able to delete a video licence constant', () => {
+ const successfullyDeleted = videoLicenceManager.deleteConstant(1)
+ expect(successfullyDeleted).to.be.true
+ expect(videoLicenceManager.getConstantValue(1)).to.be.undefined
+ })
+
+ it('Should be able to add a video licence constant', () => {
+ const successfullyAdded = videoLicenceManager.addConstant(42, 'European Union Public Licence')
+ expect(successfullyAdded).to.be.true
+ expect(videoLicenceManager.getConstantValue(42)).to.equal('European Union Public Licence')
+ })
+
+ it('Should be able to reset video licence constants', () => {
+ videoLicenceManager.deleteConstant(1)
+ videoLicenceManager.resetConstants()
+ expect(videoLicenceManager.getConstantValue(1)).not.be.undefined
+ })
+ })
+
+ describe('PlaylistPrivacyManager', () => {
+ const playlistPrivacyManager = factory.createVideoConstantManager<VideoPlaylistPrivacy>('playlistPrivacy')
+ it('Should be able to list all video playlist privacy constants', () => {
+ const constants = playlistPrivacyManager.getConstants()
+ expect(constants).to.deep.equal(VIDEO_PLAYLIST_PRIVACIES)
+ })
+
+ it('Should be able to delete a video playlist privacy constant', () => {
+ const successfullyDeleted = playlistPrivacyManager.deleteConstant(1)
+ expect(successfullyDeleted).to.be.true
+ expect(playlistPrivacyManager.getConstantValue(1)).to.be.undefined
+ })
+
+ it('Should be able to add a video playlist privacy constant', () => {
+ const successfullyAdded = playlistPrivacyManager.addConstant(42, 'Friends only')
+ expect(successfullyAdded).to.be.true
+ expect(playlistPrivacyManager.getConstantValue(42)).to.equal('Friends only')
+ })
+
+ it('Should be able to reset video playlist privacy constants', () => {
+ playlistPrivacyManager.deleteConstant(1)
+ playlistPrivacyManager.resetConstants()
+ expect(playlistPrivacyManager.getConstantValue(1)).not.be.undefined
+ })
+ })
+
+ describe('VideoPrivacyManager', () => {
+ const videoPrivacyManager = factory.createVideoConstantManager<VideoPrivacy>('privacy')
+ it('Should be able to list all video privacy constants', () => {
+ const constants = videoPrivacyManager.getConstants()
+ expect(constants).to.deep.equal(VIDEO_PRIVACIES)
+ })
+
+ it('Should be able to delete a video privacy constant', () => {
+ const successfullyDeleted = videoPrivacyManager.deleteConstant(1)
+ expect(successfullyDeleted).to.be.true
+ expect(videoPrivacyManager.getConstantValue(1)).to.be.undefined
+ })
+
+ it('Should be able to add a video privacy constant', () => {
+ const successfullyAdded = videoPrivacyManager.addConstant(42, 'Friends only')
+ expect(successfullyAdded).to.be.true
+ expect(videoPrivacyManager.getConstantValue(42)).to.equal('Friends only')
+ })
+
+ it('Should be able to reset video privacy constants', () => {
+ videoPrivacyManager.deleteConstant(1)
+ videoPrivacyManager.resetConstants()
+ expect(videoPrivacyManager.getConstantValue(1)).not.be.undefined
+ })
+ })
+
+ describe('VideoLanguageManager', () => {
+ const videoLanguageManager = factory.createVideoConstantManager<string>('language')
+ it('Should be able to list all video language constants', () => {
+ const constants = videoLanguageManager.getConstants()
+ expect(constants).to.deep.equal(VIDEO_LANGUAGES)
+ })
+
+ it('Should be able to add a video language constant', () => {
+ const successfullyAdded = videoLanguageManager.addConstant('fr', 'Fr occitan')
+ expect(successfullyAdded).to.be.true
+ expect(videoLanguageManager.getConstantValue('fr')).to.equal('Fr occitan')
+ })
+
+ it('Should be able to delete a video language constant', () => {
+ videoLanguageManager.addConstant('fr', 'Fr occitan')
+ const successfullyDeleted = videoLanguageManager.deleteConstant('fr')
+ expect(successfullyDeleted).to.be.true
+ expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
+ })
+
+ it('Should be able to reset video language constants', () => {
+ videoLanguageManager.addConstant('fr', 'Fr occitan')
+ videoLanguageManager.resetConstants()
+ expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
+ })
+ })
+})
import 'mocha'
import * as chai from 'chai'
-import {
- addVideoChannel,
- cleanupTests,
- createUser,
- flushAndRunServer,
- makeGetRequest,
- ServerInfo,
- setAccessTokensToServers,
- uploadVideo
-} from '../../shared/extra-utils'
-import { VideoPrivacy } from '../../shared/models/videos'
-import { HttpStatusCode } from '@shared/core-utils'
+import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
+import { HttpStatusCode, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test misc endpoints', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(120000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
})
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/security.txt',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('security issue')
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/nodeinfo',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.links).to.be.an('array')
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/dnt-policy.txt',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('http://www.w3.org/TR/tracking-dnt')
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/dnt',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.tracking).to.equal('N')
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/change-password',
- statusCodeExpected: HttpStatusCode.FOUND_302
+ expectedStatus: HttpStatusCode.FOUND_302
})
expect(res.header.location).to.equal('/my-account/settings')
const res = await makeGetRequest({
url: server.url,
path: '/.well-known/webfinger?resource=' + resource,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
const data = res.body
const res = await makeGetRequest({
url: server.url,
path: '/robots.txt',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('User-agent')
await makeGetRequest({
url: server.url,
path: '/security.txt',
- statusCodeExpected: HttpStatusCode.MOVED_PERMANENTLY_301
+ expectedStatus: HttpStatusCode.MOVED_PERMANENTLY_301
})
})
const res = await makeGetRequest({
url: server.url,
path: '/nodeinfo/2.0.json',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.software.name).to.equal('peertube')
const res = await makeGetRequest({
url: server.url,
path: '/sitemap.xml',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
const res = await makeGetRequest({
url: server.url,
path: '/sitemap.xml',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
it('Should add videos, channel and accounts and get sitemap', async function () {
this.timeout(35000)
- await uploadVideo(server.url, server.accessToken, { name: 'video 1', nsfw: false })
- await uploadVideo(server.url, server.accessToken, { name: 'video 2', nsfw: false })
- await uploadVideo(server.url, server.accessToken, { name: 'video 3', privacy: VideoPrivacy.PRIVATE })
+ await server.videos.upload({ attributes: { name: 'video 1', nsfw: false } })
+ await server.videos.upload({ attributes: { name: 'video 2', nsfw: false } })
+ await server.videos.upload({ attributes: { name: 'video 3', privacy: VideoPrivacy.PRIVATE } })
- await addVideoChannel(server.url, server.accessToken, { name: 'channel1', displayName: 'channel 1' })
- await addVideoChannel(server.url, server.accessToken, { name: 'channel2', displayName: 'channel 2' })
+ await server.channels.create({ attributes: { name: 'channel1', displayName: 'channel 1' } })
+ await server.channels.create({ attributes: { name: 'channel2', displayName: 'channel 2' } })
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'user1', password: 'password' })
- await createUser({ url: server.url, accessToken: server.accessToken, username: 'user2', password: 'password' })
+ await server.users.create({ username: 'user1', password: 'password' })
+ await server.users.create({ username: 'user2', password: 'password' })
const res = await makeGetRequest({
url: server.url,
path: '/sitemap.xml?t=1', // avoid using cache
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { ServerHookName, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
-import {
- addVideoCommentReply,
- addVideoCommentThread,
- addVideoInPlaylist,
- blockUser,
- createLive,
- createUser,
- createVideoPlaylist,
- deleteVideoComment,
- getPluginTestPath,
- installPlugin,
- registerUser,
- removeUser,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- unblockUser,
- updateUser,
- updateVideo,
- uploadVideo,
- userLogin,
- viewVideo
-} from '../../../shared/extra-utils'
import {
cleanupTests,
- flushAndRunMultipleServers,
+ createMultipleServers,
killallServers,
- reRunServer,
- ServerInfo,
- waitUntilLog
-} from '../../../shared/extra-utils/server/servers'
+ PeerTubeServer,
+ PluginsCommand,
+ setAccessTokensToServers,
+ setDefaultVideoChannel
+} from '@shared/extra-utils'
+import { ServerHookName, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
describe('Test plugin action hooks', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoUUID: string
let threadId: number
function checkHook (hook: ServerHookName) {
- return waitUntilLog(servers[0], 'Run hook ' + hook)
+ return servers[0].servers.waitUntilLog('Run hook ' + hook)
}
before(async function () {
this.timeout(30000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
- await installPlugin({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- path: getPluginTestPath()
- })
+ await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
- killallServers([ servers[0] ])
+ await killallServers([ servers[0] ])
- await reRunServer(servers[0], {
+ await servers[0].run({
live: {
enabled: true
}
describe('Videos hooks', function () {
it('Should run action:api.video.uploaded', async function () {
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
- videoUUID = res.body.video.uuid
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' } })
+ videoUUID = uuid
await checkHook('action:api.video.uploaded')
})
it('Should run action:api.video.updated', async function () {
- await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, { name: 'video updated' })
+ await servers[0].videos.update({ id: videoUUID, attributes: { name: 'video updated' } })
await checkHook('action:api.video.updated')
})
it('Should run action:api.video.viewed', async function () {
- await viewVideo(servers[0].url, videoUUID)
+ await servers[0].videos.view({ id: videoUUID })
await checkHook('action:api.video.viewed')
})
const attributes = {
name: 'live',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id
+ channelId: servers[0].store.channel.id
}
- await createLive(servers[0].url, servers[0].accessToken, attributes)
+ await servers[0].live.create({ fields: attributes })
await checkHook('action:api.live-video.created')
})
describe('Comments hooks', function () {
it('Should run action:api.video-thread.created', async function () {
- const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
- threadId = res.body.comment.id
+ const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
+ threadId = created.id
await checkHook('action:api.video-thread.created')
})
it('Should run action:api.video-comment-reply.created', async function () {
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'reply')
+ await servers[0].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: 'reply' })
await checkHook('action:api.video-comment-reply.created')
})
it('Should run action:api.video-comment.deleted', async function () {
- await deleteVideoComment(servers[0].url, servers[0].accessToken, videoUUID, threadId)
+ await servers[0].comments.delete({ videoId: videoUUID, commentId: threadId })
await checkHook('action:api.video-comment.deleted')
})
let userId: number
it('Should run action:api.user.registered', async function () {
- await registerUser(servers[0].url, 'registered_user', 'super_password')
+ await servers[0].users.register({ username: 'registered_user' })
await checkHook('action:api.user.registered')
})
it('Should run action:api.user.created', async function () {
- const res = await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: 'created_user',
- password: 'super_password'
- })
- userId = res.body.user.id
+ const user = await servers[0].users.create({ username: 'created_user' })
+ userId = user.id
await checkHook('action:api.user.created')
})
it('Should run action:api.user.oauth2-got-token', async function () {
- await userLogin(servers[0], { username: 'created_user', password: 'super_password' })
+ await servers[0].login.login({ user: { username: 'created_user' } })
await checkHook('action:api.user.oauth2-got-token')
})
it('Should run action:api.user.blocked', async function () {
- await blockUser(servers[0].url, userId, servers[0].accessToken)
+ await servers[0].users.banUser({ userId })
await checkHook('action:api.user.blocked')
})
it('Should run action:api.user.unblocked', async function () {
- await unblockUser(servers[0].url, userId, servers[0].accessToken)
+ await servers[0].users.unbanUser({ userId })
await checkHook('action:api.user.unblocked')
})
it('Should run action:api.user.updated', async function () {
- await updateUser({ url: servers[0].url, accessToken: servers[0].accessToken, userId, videoQuota: 50 })
+ await servers[0].users.update({ userId, videoQuota: 50 })
await checkHook('action:api.user.updated')
})
it('Should run action:api.user.deleted', async function () {
- await removeUser(servers[0].url, userId, servers[0].accessToken)
+ await servers[0].users.remove({ userId })
await checkHook('action:api.user.deleted')
})
before(async function () {
{
- const res = await createVideoPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistAttrs: {
+ const { id } = await servers[0].playlists.create({
+ attributes: {
displayName: 'My playlist',
privacy: VideoPlaylistPrivacy.PRIVATE
}
})
- playlistId = res.body.videoPlaylist.id
+ playlistId = id
}
{
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'my super name' })
- videoId = res.body.video.id
+ const { id } = await servers[0].videos.upload({ attributes: { name: 'my super name' } })
+ videoId = id
}
})
it('Should run action:api.video-playlist-element.created', async function () {
- await addVideoInPlaylist({
- url: servers[0].url,
- token: servers[0].accessToken,
- playlistId,
- elementAttrs: { videoId }
- })
+ await servers[0].playlists.addElement({ playlistId, attributes: { videoId } })
await checkHook('action:api.video-playlist-element.created')
})
import 'mocha'
import { expect } from 'chai'
-import { ServerConfig, User, UserRole } from '@shared/models'
import {
+ cleanupTests,
+ createSingleServer,
decodeQueryString,
- getConfig,
- getExternalAuth,
- getMyUserInformation,
- getPluginTestPath,
- installPlugin,
- loginUsingExternalToken,
- logout,
- refreshToken,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers,
- uninstallPlugin,
- updateMyUser,
- wait,
- userLogin,
- updatePluginSettings,
- createUser
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+ wait
+} from '@shared/extra-utils'
+import { HttpStatusCode, UserRole } from '@shared/models'
async function loginExternal (options: {
- server: ServerInfo
+ server: PeerTubeServer
npmName: string
authName: string
username: string
query?: any
- statusCodeExpected?: HttpStatusCode
- statusCodeExpectedStep2?: HttpStatusCode
+ expectedStatus?: HttpStatusCode
+ expectedStatusStep2?: HttpStatusCode
}) {
- const res = await getExternalAuth({
- url: options.server.url,
+ const res = await options.server.plugins.getExternalAuth({
npmName: options.npmName,
npmVersion: '0.0.1',
authName: options.authName,
query: options.query,
- statusCodeExpected: options.statusCodeExpected || HttpStatusCode.FOUND_302
+ expectedStatus: options.expectedStatus || HttpStatusCode.FOUND_302
})
if (res.status !== HttpStatusCode.FOUND_302) return
const location = res.header.location
const { externalAuthToken } = decodeQueryString(location)
- const resLogin = await loginUsingExternalToken(
- options.server,
- options.username,
- externalAuthToken as string,
- options.statusCodeExpectedStep2
- )
+ const resLogin = await options.server.login.loginUsingExternalToken({
+ username: options.username,
+ externalAuthToken: externalAuthToken as string,
+ expectedStatus: options.expectedStatusStep2
+ })
return resLogin.body
}
describe('Test external auth plugins', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let cyanAccessToken: string
let cyanRefreshToken: string
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
for (const suffix of [ 'one', 'two', 'three' ]) {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-external-auth-' + suffix)
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-external-auth-' + suffix) })
}
})
it('Should display the correct configuration', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredExternalAuths
expect(auths).to.have.lengthOf(8)
})
it('Should redirect for a Cyan login', async function () {
- const res = await getExternalAuth({
- url: server.url,
+ const res = await server.plugins.getExternalAuth({
npmName: 'test-external-auth-one',
npmVersion: '0.0.1',
authName: 'external-auth-1',
query: {
username: 'cyan'
},
- statusCodeExpected: HttpStatusCode.FOUND_302
+ expectedStatus: HttpStatusCode.FOUND_302
})
const location = res.header.location
})
it('Should reject auto external login with a missing or invalid token', async function () {
- await loginUsingExternalToken(server, 'cyan', '', HttpStatusCode.BAD_REQUEST_400)
- await loginUsingExternalToken(server, 'cyan', 'blabla', HttpStatusCode.BAD_REQUEST_400)
+ const command = server.login
+
+ await command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should reject auto external login with a missing or invalid username', async function () {
- await loginUsingExternalToken(server, '', externalAuthToken, HttpStatusCode.BAD_REQUEST_400)
- await loginUsingExternalToken(server, '', externalAuthToken, HttpStatusCode.BAD_REQUEST_400)
+ const command = server.login
+
+ await command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should reject auto external login with an expired token', async function () {
await wait(5000)
- await loginUsingExternalToken(server, 'cyan', externalAuthToken, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.loginUsingExternalToken({
+ username: 'cyan',
+ externalAuthToken,
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
+ })
- await waitUntilLog(server, 'expired external auth token', 2)
+ await server.servers.waitUntilLog('expired external auth token', 2)
})
it('Should auto login Cyan, create the user and use the token', async function () {
}
{
- const res = await getMyUserInformation(server.url, cyanAccessToken)
-
- const body: User = res.body
+ const body = await server.users.getMyInfo({ token: cyanAccessToken })
expect(body.username).to.equal('cyan')
expect(body.account.displayName).to.equal('cyan')
expect(body.email).to.equal('cyan@example.com')
}
{
- const res = await getMyUserInformation(server.url, kefkaAccessToken)
-
- const body: User = res.body
+ const body = await server.users.getMyInfo({ token: kefkaAccessToken })
expect(body.username).to.equal('kefka')
expect(body.account.displayName).to.equal('Kefka Palazzo')
expect(body.email).to.equal('kefka@example.com')
it('Should refresh Cyan token, but not Kefka token', async function () {
{
- const resRefresh = await refreshToken(server, cyanRefreshToken)
+ const resRefresh = await server.login.refreshToken({ refreshToken: cyanRefreshToken })
cyanAccessToken = resRefresh.body.access_token
cyanRefreshToken = resRefresh.body.refresh_token
- const res = await getMyUserInformation(server.url, cyanAccessToken)
- const user: User = res.body
- expect(user.username).to.equal('cyan')
+ const body = await server.users.getMyInfo({ token: cyanAccessToken })
+ expect(body.username).to.equal('cyan')
}
{
- await refreshToken(server, kefkaRefreshToken, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.refreshToken({ refreshToken: kefkaRefreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
})
it('Should update Cyan profile', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: cyanAccessToken,
+ await server.users.updateMe({
+ token: cyanAccessToken,
displayName: 'Cyan Garamonde',
description: 'Retainer to the king of Doma'
})
- const res = await getMyUserInformation(server.url, cyanAccessToken)
-
- const body: User = res.body
+ const body = await server.users.getMyInfo({ token: cyanAccessToken })
expect(body.account.displayName).to.equal('Cyan Garamonde')
expect(body.account.description).to.equal('Retainer to the king of Doma')
})
it('Should logout Cyan', async function () {
- await logout(server.url, cyanAccessToken)
+ await server.login.logout({ token: cyanAccessToken })
})
it('Should have logged out Cyan', async function () {
- await waitUntilLog(server, 'On logout cyan')
+ await server.servers.waitUntilLog('On logout cyan')
- await getMyUserInformation(server.url, cyanAccessToken, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyInfo({ token: cyanAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should login Cyan and keep the old existing profile', async function () {
cyanAccessToken = res.access_token
}
- const res = await getMyUserInformation(server.url, cyanAccessToken)
-
- const body: User = res.body
+ const body = await server.users.getMyInfo({ token: cyanAccessToken })
expect(body.username).to.equal('cyan')
expect(body.account.displayName).to.equal('Cyan Garamonde')
expect(body.account.description).to.equal('Retainer to the king of Doma')
})
it('Should not update an external auth email', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: cyanAccessToken,
+ await server.users.updateMe({
+ token: cyanAccessToken,
email: 'toto@example.com',
currentPassword: 'toto',
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
})
await wait(5000)
- await getMyUserInformation(server.url, kefkaAccessToken, HttpStatusCode.UNAUTHORIZED_401)
+ await server.users.getMyInfo({ token: kefkaAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should unregister external-auth-2 and do not login existing Kefka', async function () {
- await updatePluginSettings({
- url: server.url,
- accessToken: server.accessToken,
+ await server.plugins.updateSettings({
npmName: 'peertube-plugin-test-external-auth-one',
settings: { disableKefka: true }
})
- await userLogin(server, { username: 'kefka', password: 'fake' }, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.login({ user: { username: 'kefka', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
await loginExternal({
server,
username: 'kefka'
},
username: 'kefka',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should have disabled this auth', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredExternalAuths
expect(auths).to.have.lengthOf(7)
})
it('Should uninstall the plugin one and do not login Cyan', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-test-external-auth-one'
- })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-external-auth-one' })
await loginExternal({
server,
username: 'cyan'
},
username: 'cyan',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
- await userLogin(server, { username: 'cyan', password: null }, HttpStatusCode.BAD_REQUEST_400)
- await userLogin(server, { username: 'cyan', password: '' }, HttpStatusCode.BAD_REQUEST_400)
- await userLogin(server, { username: 'cyan', password: 'fake' }, HttpStatusCode.BAD_REQUEST_400)
+ await server.login.login({ user: { username: 'cyan', password: null }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.login.login({ user: { username: 'cyan', password: '' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.login.login({ user: { username: 'cyan', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not login kefka with another plugin', async function () {
npmName: 'test-external-auth-two',
authName: 'external-auth-4',
username: 'kefka2',
- statusCodeExpectedStep2: HttpStatusCode.BAD_REQUEST_400
+ expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
})
await loginExternal({
npmName: 'test-external-auth-two',
authName: 'external-auth-4',
username: 'kefka',
- statusCodeExpectedStep2: HttpStatusCode.BAD_REQUEST_400
+ expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should not login an existing user', async function () {
- await createUser({
- url: server.url,
- accessToken: server.accessToken,
- username: 'existing_user',
- password: 'super_password'
- })
+ await server.users.create({ username: 'existing_user', password: 'super_password' })
await loginExternal({
server,
npmName: 'test-external-auth-two',
authName: 'external-auth-6',
username: 'existing_user',
- statusCodeExpectedStep2: HttpStatusCode.BAD_REQUEST_400
+ expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
})
})
it('Should display the correct configuration', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredExternalAuths
expect(auths).to.have.lengthOf(6)
username: 'cid'
})
- const resLogout = await logout(server.url, resLogin.access_token)
-
- expect(resLogout.body.redirectUrl).to.equal('https://example.com/redirectUrl')
+ const { redirectUrl } = await server.login.logout({ token: resLogin.access_token })
+ expect(redirectUrl).to.equal('https://example.com/redirectUrl')
})
it('Should call the plugin\'s onLogout method with the request', async function () {
username: 'cid'
})
- const resLogout = await logout(server.url, resLogin.access_token)
-
- expect(resLogout.body.redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token)
+ const { redirectUrl } = await server.login.logout({ token: resLogin.access_token })
+ expect(redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token)
})
})
import 'mocha'
import * as chai from 'chai'
-import { advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels'
-import { ServerConfig } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
import {
- addVideoCommentReply,
- addVideoCommentThread,
- advancedVideoPlaylistSearch,
- advancedVideosSearch,
- createLive,
- createVideoPlaylist,
+ cleanupTests,
+ createMultipleServers,
doubleFollow,
- getAccountVideos,
- getConfig,
- getMyVideos,
- getPluginTestPath,
- getVideo,
- getVideoChannelVideos,
- getVideoCommentThreads,
- getVideoPlaylist,
- getVideosList,
- getVideosListPagination,
- getVideoThreadComments,
- getVideoWithToken,
- installPlugin,
+ FIXTURE_URLS,
makeRawRequest,
- registerUser,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers,
setDefaultVideoChannel,
- updateCustomSubConfig,
- updateVideo,
- uploadVideo,
- uploadVideoAndGetId,
waitJobs
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
-import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
-import {
- VideoCommentThreadTree,
- VideoDetails,
- VideoImport,
- VideoImportState,
- VideoPlaylist,
- VideoPlaylistPrivacy,
- VideoPrivacy
-} from '../../../shared/models/videos'
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test plugin filter hooks', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
let videoUUID: string
let threadId: number
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
await doubleFollow(servers[0], servers[1])
- await installPlugin({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- path: getPluginTestPath()
- })
-
- await installPlugin({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- path: getPluginTestPath('-filter-translations')
- })
+ await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
+ await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
for (let i = 0; i < 10; i++) {
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'default video ' + i })
+ await servers[0].videos.upload({ attributes: { name: 'default video ' + i } })
}
- const res = await getVideosList(servers[0].url)
- videoUUID = res.body.data[0].uuid
-
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- live: { enabled: true },
- signup: { enabled: true },
- import: {
- videos: {
- http: { enabled: true },
- torrent: { enabled: true }
+ const { data } = await servers[0].videos.list()
+ videoUUID = data[0].uuid
+
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ live: { enabled: true },
+ signup: { enabled: true },
+ import: {
+ videos: {
+ http: { enabled: true },
+ torrent: { enabled: true }
+ }
}
}
})
})
it('Should run filter:api.videos.list.params', async function () {
- const res = await getVideosListPagination(servers[0].url, 0, 2)
+ const { data } = await servers[0].videos.list({ start: 0, count: 2 })
// 2 plugins do +1 to the count parameter
- expect(res.body.data).to.have.lengthOf(4)
+ expect(data).to.have.lengthOf(4)
})
it('Should run filter:api.videos.list.result', async function () {
- const res = await getVideosListPagination(servers[0].url, 0, 0)
+ const { total } = await servers[0].videos.list({ start: 0, count: 0 })
// Plugin do +1 to the total result
- expect(res.body.total).to.equal(11)
+ expect(total).to.equal(11)
})
it('Should run filter:api.accounts.videos.list.params', async function () {
- const res = await getAccountVideos(servers[0].url, servers[0].accessToken, 'root', 0, 2)
+ const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// 1 plugin do +1 to the count parameter
- expect(res.body.data).to.have.lengthOf(3)
+ expect(data).to.have.lengthOf(3)
})
it('Should run filter:api.accounts.videos.list.result', async function () {
- const res = await getAccountVideos(servers[0].url, servers[0].accessToken, 'root', 0, 2)
+ const { total } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// Plugin do +2 to the total result
- expect(res.body.total).to.equal(12)
+ expect(total).to.equal(12)
})
it('Should run filter:api.video-channels.videos.list.params', async function () {
- const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, 'root_channel', 0, 2)
+ const { data } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// 1 plugin do +3 to the count parameter
- expect(res.body.data).to.have.lengthOf(5)
+ expect(data).to.have.lengthOf(5)
})
it('Should run filter:api.video-channels.videos.list.result', async function () {
- const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, 'root_channel', 0, 2)
+ const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// Plugin do +3 to the total result
- expect(res.body.total).to.equal(13)
+ expect(total).to.equal(13)
})
it('Should run filter:api.user.me.videos.list.params', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 2)
+ const { data } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// 1 plugin do +4 to the count parameter
- expect(res.body.data).to.have.lengthOf(6)
+ expect(data).to.have.lengthOf(6)
})
it('Should run filter:api.user.me.videos.list.result', async function () {
- const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 2)
+ const { total } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// Plugin do +4 to the total result
- expect(res.body.total).to.equal(14)
+ expect(total).to.equal(14)
})
it('Should run filter:api.video.get.result', async function () {
- const res = await getVideo(servers[0].url, videoUUID)
-
- expect(res.body.name).to.contain('<3')
+ const video = await servers[0].videos.get({ id: videoUUID })
+ expect(video.name).to.contain('<3')
})
it('Should run filter:api.video.upload.accept.result', async function () {
- await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].videos.upload({ attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.live-video.create.accept.result', async function () {
const attributes = {
name: 'video with bad word',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id
+ channelId: servers[0].store.channel.id
}
- await createLive(servers[0].url, servers[0].accessToken, attributes, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].live.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
- const baseAttributes = {
+ const attributes = {
name: 'normal title',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id,
- targetUrl: getGoodVideoUrl() + 'bad'
+ channelId: servers[0].store.channel.id,
+ targetUrl: FIXTURE_URLS.goodVideo + 'bad'
}
- await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
- const baseAttributes = {
+ const attributes = {
name: 'bad torrent',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
torrentfile: 'video-720p.torrent' as any
}
- await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
+ await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.post-import-url.accept.result', async function () {
let videoImportId: number
{
- const baseAttributes = {
+ const attributes = {
name: 'title with bad word',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id,
- targetUrl: getGoodVideoUrl()
+ channelId: servers[0].store.channel.id,
+ targetUrl: FIXTURE_URLS.goodVideo
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, baseAttributes)
- videoImportId = res.body.id
+ const body = await servers[0].imports.importVideo({ attributes })
+ videoImportId = body.id
}
await waitJobs(servers)
{
- const res = await getMyVideoImports(servers[0].url, servers[0].accessToken)
- const videoImports = res.body.data as VideoImport[]
+ const body = await servers[0].imports.getMyVideoImports()
+ const videoImports = body.data
const videoImport = videoImports.find(i => i.id === videoImportId)
let videoImportId: number
{
- const baseAttributes = {
+ const attributes = {
name: 'title with bad word',
privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].videoChannel.id,
+ channelId: servers[0].store.channel.id,
torrentfile: 'video-720p.torrent' as any
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, baseAttributes)
- videoImportId = res.body.id
+ const body = await servers[0].imports.importVideo({ attributes })
+ videoImportId = body.id
}
await waitJobs(servers)
{
- const res = await getMyVideoImports(servers[0].url, servers[0].accessToken)
- const videoImports = res.body.data as VideoImport[]
+ const { data: videoImports } = await servers[0].imports.getMyVideoImports()
const videoImport = videoImports.find(i => i.id === videoImportId)
})
it('Should run filter:api.video-thread.create.accept.result', async function () {
- await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', HttpStatusCode.FORBIDDEN_403)
+ await servers[0].comments.createThread({
+ videoId: videoUUID,
+ text: 'comment with bad word',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
})
it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
- const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
- threadId = res.body.comment.id
-
- await addVideoCommentReply(
- servers[0].url,
- servers[0].accessToken,
- videoUUID,
- threadId,
- 'comment with bad word',
- HttpStatusCode.FORBIDDEN_403
- )
- await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', HttpStatusCode.OK_200)
+ const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
+ threadId = created.id
+
+ await servers[0].comments.addReply({
+ videoId: videoUUID,
+ toCommentId: threadId,
+ text: 'comment with bad word',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
+ await servers[0].comments.addReply({
+ videoId: videoUUID,
+ toCommentId: threadId,
+ text: 'comment with good word',
+ expectedStatus: HttpStatusCode.OK_200
+ })
})
it('Should run filter:api.video-threads.list.params', async function () {
- const res = await getVideoCommentThreads(servers[0].url, videoUUID, 0, 0)
+ const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
// our plugin do +1 to the count parameter
- expect(res.body.data).to.have.lengthOf(1)
+ expect(data).to.have.lengthOf(1)
})
it('Should run filter:api.video-threads.list.result', async function () {
- const res = await getVideoCommentThreads(servers[0].url, videoUUID, 0, 0)
+ const { total } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
// Plugin do +1 to the total result
- expect(res.body.total).to.equal(2)
+ expect(total).to.equal(2)
})
it('Should run filter:api.video-thread-comments.list.params')
it('Should run filter:api.video-thread-comments.list.result', async function () {
- const res = await getVideoThreadComments(servers[0].url, videoUUID, threadId)
+ const thread = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
- const thread = res.body as VideoCommentThreadTree
expect(thread.comment.text.endsWith(' <3')).to.be.true
})
- describe('Should run filter:video.auto-blacklist.result', function () {
+ it('Should run filter:api.overviews.videos.list.{params,result}', async function () {
+ await servers[0].overviews.getVideos({ page: 1 })
- async function checkIsBlacklisted (oldRes: any, value: boolean) {
- const videoId = oldRes.body.video.uuid
+ // 3 because we get 3 samples per page
+ await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.params', 3)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
+ })
- const res = await getVideoWithToken(servers[0].url, servers[0].accessToken, videoId)
- const video: VideoDetails = res.body
+ describe('Should run filter:video.auto-blacklist.result', function () {
+
+ async function checkIsBlacklisted (id: number | string, value: boolean) {
+ const video = await servers[0].videos.getWithToken({ id })
expect(video.blacklisted).to.equal(value)
}
it('Should blacklist on upload', async function () {
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video please blacklist me' })
- await checkIsBlacklisted(res, true)
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video please blacklist me' } })
+ await checkIsBlacklisted(uuid, true)
})
it('Should blacklist on import', async function () {
const attributes = {
name: 'video please blacklist me',
- targetUrl: getGoodVideoUrl(),
- channelId: servers[0].videoChannel.id
+ targetUrl: FIXTURE_URLS.goodVideo,
+ channelId: servers[0].store.channel.id
}
- const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
- await checkIsBlacklisted(res, true)
+ const body = await servers[0].imports.importVideo({ attributes })
+ await checkIsBlacklisted(body.video.uuid, true)
})
it('Should blacklist on update', async function () {
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
- const videoId = res.body.video.uuid
- await checkIsBlacklisted(res, false)
+ const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' } })
+ await checkIsBlacklisted(uuid, false)
- await updateVideo(servers[0].url, servers[0].accessToken, videoId, { name: 'please blacklist me' })
- await checkIsBlacklisted(res, true)
+ await servers[0].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
+ await checkIsBlacklisted(uuid, true)
})
it('Should blacklist on remote upload', async function () {
this.timeout(120000)
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'remote please blacklist me' })
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'remote please blacklist me' } })
await waitJobs(servers)
- await checkIsBlacklisted(res, true)
+ await checkIsBlacklisted(uuid, true)
})
it('Should blacklist on remote update', async function () {
this.timeout(120000)
- const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video' })
+ const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video' } })
await waitJobs(servers)
- const videoId = res.body.video.uuid
- await checkIsBlacklisted(res, false)
+ await checkIsBlacklisted(uuid, false)
- await updateVideo(servers[1].url, servers[1].accessToken, videoId, { name: 'please blacklist me' })
+ await servers[1].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
await waitJobs(servers)
- await checkIsBlacklisted(res, true)
+ await checkIsBlacklisted(uuid, true)
})
})
describe('Should run filter:api.user.signup.allowed.result', function () {
it('Should run on config endpoint', async function () {
- const res = await getConfig(servers[0].url)
- expect((res.body as ServerConfig).signup.allowed).to.be.true
+ const body = await servers[0].config.getConfig()
+ expect(body.signup.allowed).to.be.true
})
it('Should allow a signup', async function () {
- await registerUser(servers[0].url, 'john', 'password')
+ await servers[0].users.register({ username: 'john', password: 'password' })
})
it('Should not allow a signup', async function () {
- const res = await registerUser(servers[0].url, 'jma', 'password', HttpStatusCode.FORBIDDEN_403)
+ const res = await servers[0].users.register({
+ username: 'jma',
+ password: 'password',
+ expectedStatus: HttpStatusCode.FORBIDDEN_403
+ })
expect(res.body.error).to.equal('No jma')
})
before(async function () {
this.timeout(120000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- webtorrent: {
- enabled: true
- },
- hls: {
- enabled: true
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ webtorrent: {
+ enabled: true
+ },
+ hls: {
+ enabled: true
+ }
}
}
})
const uuids: string[] = []
for (const name of [ 'bad torrent', 'bad file', 'bad playlist file' ]) {
- const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
+ const uuid = (await servers[0].videos.quickUpload({ name: name })).uuid
uuids.push(uuid)
}
await waitJobs(servers)
for (const uuid of uuids) {
- const res = await getVideo(servers[0].url, uuid)
- downloadVideos.push(res.body)
+ downloadVideos.push(await servers[0].videos.get({ id: uuid }))
}
})
before(async function () {
this.timeout(60000)
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- transcoding: {
- enabled: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ transcoding: {
+ enabled: false
+ }
}
})
for (const name of [ 'bad embed', 'good embed' ]) {
{
- const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
- const res = await getVideo(servers[0].url, uuid)
- embedVideos.push(res.body)
+ const uuid = (await servers[0].videos.quickUpload({ name: name })).uuid
+ embedVideos.push(await servers[0].videos.get({ id: uuid }))
}
{
- const playlistAttrs = { displayName: name, videoChannelId: servers[0].videoChannel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
- const res = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs })
+ const attributes = { displayName: name, videoChannelId: servers[0].store.channel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
+ const { id } = await servers[0].playlists.create({ attributes })
- const resPlaylist = await getVideoPlaylist(servers[0].url, res.body.videoPlaylist.id)
- embedPlaylists.push(resPlaylist.body)
+ const playlist = await servers[0].playlists.get({ playlistId: id })
+ embedPlaylists.push(playlist)
}
}
})
describe('Search filters', function () {
before(async function () {
- await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: false,
- disableLocalSearch: false
+ await servers[0].config.updateCustomSubConfig({
+ newConfig: {
+ search: {
+ searchIndex: {
+ enabled: true,
+ isDefaultSearch: false,
+ disableLocalSearch: false
+ }
}
}
})
})
it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
- await advancedVideosSearch(servers[0].url, {
- search: 'Sun Quan'
+ await servers[0].search.advancedVideoSearch({
+ search: {
+ search: 'Sun Quan'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
})
it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
- await advancedVideosSearch(servers[0].url, {
- search: 'Sun Quan',
- searchTarget: 'search-index'
+ await servers[0].search.advancedVideoSearch({
+ search: {
+ search: 'Sun Quan',
+ searchTarget: 'search-index'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.result', 1)
})
it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
- await advancedVideoChannelSearch(servers[0].url, {
- search: 'Sun Ce'
+ await servers[0].search.advancedChannelSearch({
+ search: {
+ search: 'Sun Ce'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
})
it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
- await advancedVideoChannelSearch(servers[0].url, {
- search: 'Sun Ce',
- searchTarget: 'search-index'
+ await servers[0].search.advancedChannelSearch({
+ search: {
+ search: 'Sun Ce',
+ searchTarget: 'search-index'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.result', 1)
})
it('Should run filter:api.search.video-playlists.local.list.{params,result}', async function () {
- await advancedVideoPlaylistSearch(servers[0].url, {
- search: 'Sun Jian'
+ await servers[0].search.advancedPlaylistSearch({
+ search: {
+ search: 'Sun Jian'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
})
it('Should run filter:api.search.video-playlists.index.list.{params,result}', async function () {
- await advancedVideoPlaylistSearch(servers[0].url, {
- search: 'Sun Jian',
- searchTarget: 'search-index'
+ await servers[0].search.advancedPlaylistSearch({
+ search: {
+ search: 'Sun Jian',
+ searchTarget: 'search-index'
+ }
})
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.result', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.index.list.params', 1)
- await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.index.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.params', 1)
+ await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.result', 1)
})
})
import * as chai from 'chai'
import {
cleanupTests,
- flushAndRunServer,
- getPluginsCSS,
- installPlugin,
+ createSingleServer,
makeHTMLRequest,
- ServerInfo,
- setAccessTokensToServers,
- uninstallPlugin
+ PeerTubeServer,
+ PluginsCommand,
+ setAccessTokensToServers
} from '../../../shared/extra-utils'
const expect = chai.expect
describe('Test plugins HTML injection', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer = null
+ let command: PluginsCommand
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
+
+ command = server.plugins
})
it('Should not inject global css file in HTML', async function () {
{
- const res = await getPluginsCSS(server.url)
- expect(res.text).to.be.empty
+ const text = await command.getCSS()
+ expect(text).to.be.empty
}
for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
it('Should install a plugin and a theme', async function () {
this.timeout(30000)
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
+ await command.install({ npmName: 'peertube-plugin-hello-world' })
})
it('Should have the correct global css', async function () {
{
- const res = await getPluginsCSS(server.url)
- expect(res.text).to.contain('background-color: red')
+ const text = await command.getCSS()
+ expect(text).to.contain('background-color: red')
}
for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
})
it('Should have an empty global css on uninstall', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
+ await command.uninstall({ npmName: 'peertube-plugin-hello-world' })
{
- const res = await getPluginsCSS(server.url)
- expect(res.text).to.be.empty
+ const text = await command.getCSS()
+ expect(text).to.be.empty
}
for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
-import {
- getMyUserInformation,
- getPluginTestPath,
- installPlugin,
- logout,
- setAccessTokensToServers,
- uninstallPlugin,
- updateMyUser,
- userLogin,
- wait,
- login, refreshToken, getConfig, updatePluginSettings, getUsersList
-} from '../../../shared/extra-utils'
-import { User, UserRole, ServerConfig } from '@shared/models'
import { expect } from 'chai'
+import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { HttpStatusCode, UserRole } from '@shared/models'
describe('Test id and pass auth plugins', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
let crashAccessToken: string
let crashRefreshToken: string
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
for (const suffix of [ 'one', 'two', 'three' ]) {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-id-pass-auth-' + suffix)
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-id-pass-auth-' + suffix) })
}
})
it('Should display the correct configuration', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredIdAndPassAuths
expect(auths).to.have.lengthOf(8)
})
it('Should not login', async function () {
- await userLogin(server, { username: 'toto', password: 'password' }, 400)
+ await server.login.login({ user: { username: 'toto', password: 'password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should login Spyro, create the user and use the token', async function () {
- const accessToken = await userLogin(server, { username: 'spyro', password: 'spyro password' })
+ const accessToken = await server.login.getAccessToken({ username: 'spyro', password: 'spyro password' })
- const res = await getMyUserInformation(server.url, accessToken)
+ const body = await server.users.getMyInfo({ token: accessToken })
- const body: User = res.body
expect(body.username).to.equal('spyro')
expect(body.account.displayName).to.equal('Spyro the Dragon')
expect(body.role).to.equal(UserRole.USER)
it('Should login Crash, create the user and use the token', async function () {
{
- const res = await login(server.url, server.client, { username: 'crash', password: 'crash password' })
- crashAccessToken = res.body.access_token
- crashRefreshToken = res.body.refresh_token
+ const body = await server.login.login({ user: { username: 'crash', password: 'crash password' } })
+ crashAccessToken = body.access_token
+ crashRefreshToken = body.refresh_token
}
{
- const res = await getMyUserInformation(server.url, crashAccessToken)
+ const body = await server.users.getMyInfo({ token: crashAccessToken })
- const body: User = res.body
expect(body.username).to.equal('crash')
expect(body.account.displayName).to.equal('Crash Bandicoot')
expect(body.role).to.equal(UserRole.MODERATOR)
it('Should login the first Laguna, create the user and use the token', async function () {
{
- const res = await login(server.url, server.client, { username: 'laguna', password: 'laguna password' })
- lagunaAccessToken = res.body.access_token
- lagunaRefreshToken = res.body.refresh_token
+ const body = await server.login.login({ user: { username: 'laguna', password: 'laguna password' } })
+ lagunaAccessToken = body.access_token
+ lagunaRefreshToken = body.refresh_token
}
{
- const res = await getMyUserInformation(server.url, lagunaAccessToken)
+ const body = await server.users.getMyInfo({ token: lagunaAccessToken })
- const body: User = res.body
expect(body.username).to.equal('laguna')
expect(body.account.displayName).to.equal('laguna')
expect(body.role).to.equal(UserRole.USER)
it('Should refresh crash token, but not laguna token', async function () {
{
- const resRefresh = await refreshToken(server, crashRefreshToken)
+ const resRefresh = await server.login.refreshToken({ refreshToken: crashRefreshToken })
crashAccessToken = resRefresh.body.access_token
crashRefreshToken = resRefresh.body.refresh_token
- const res = await getMyUserInformation(server.url, crashAccessToken)
- const user: User = res.body
- expect(user.username).to.equal('crash')
+ const body = await server.users.getMyInfo({ token: crashAccessToken })
+ expect(body.username).to.equal('crash')
}
{
- await refreshToken(server, lagunaRefreshToken, 400)
+ await server.login.refreshToken({ refreshToken: lagunaRefreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}
})
it('Should update Crash profile', async function () {
- await updateMyUser({
- url: server.url,
- accessToken: crashAccessToken,
+ await server.users.updateMe({
+ token: crashAccessToken,
displayName: 'Beautiful Crash',
description: 'Mutant eastern barred bandicoot'
})
- const res = await getMyUserInformation(server.url, crashAccessToken)
+ const body = await server.users.getMyInfo({ token: crashAccessToken })
- const body: User = res.body
expect(body.account.displayName).to.equal('Beautiful Crash')
expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
})
it('Should logout Crash', async function () {
- await logout(server.url, crashAccessToken)
+ await server.login.logout({ token: crashAccessToken })
})
it('Should have logged out Crash', async function () {
- await waitUntilLog(server, 'On logout for auth 1 - 2')
+ await server.servers.waitUntilLog('On logout for auth 1 - 2')
- await getMyUserInformation(server.url, crashAccessToken, 401)
+ await server.users.getMyInfo({ token: crashAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should login Crash and keep the old existing profile', async function () {
- crashAccessToken = await userLogin(server, { username: 'crash', password: 'crash password' })
+ crashAccessToken = await server.login.getAccessToken({ username: 'crash', password: 'crash password' })
- const res = await getMyUserInformation(server.url, crashAccessToken)
+ const body = await server.users.getMyInfo({ token: crashAccessToken })
- const body: User = res.body
expect(body.username).to.equal('crash')
expect(body.account.displayName).to.equal('Beautiful Crash')
expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
await wait(5000)
- await getMyUserInformation(server.url, lagunaAccessToken, 401)
+ await server.users.getMyInfo({ token: lagunaAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should reject an invalid username, email, role or display name', async function () {
- await userLogin(server, { username: 'ward', password: 'ward password' }, 400)
- await waitUntilLog(server, 'valid username')
+ const command = server.login
- await userLogin(server, { username: 'kiros', password: 'kiros password' }, 400)
- await waitUntilLog(server, 'valid display name')
+ await command.login({ user: { username: 'ward', password: 'ward password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.servers.waitUntilLog('valid username')
- await userLogin(server, { username: 'raine', password: 'raine password' }, 400)
- await waitUntilLog(server, 'valid role')
+ await command.login({ user: { username: 'kiros', password: 'kiros password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.servers.waitUntilLog('valid display name')
- await userLogin(server, { username: 'ellone', password: 'elonne password' }, 400)
- await waitUntilLog(server, 'valid email')
+ await command.login({ user: { username: 'raine', password: 'raine password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.servers.waitUntilLog('valid role')
+
+ await command.login({ user: { username: 'ellone', password: 'elonne password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await server.servers.waitUntilLog('valid email')
})
it('Should unregister spyro-auth and do not login existing Spyro', async function () {
- await updatePluginSettings({
- url: server.url,
- accessToken: server.accessToken,
+ await server.plugins.updateSettings({
npmName: 'peertube-plugin-test-id-pass-auth-one',
settings: { disableSpyro: true }
})
- await userLogin(server, { username: 'spyro', password: 'spyro password' }, 400)
- await userLogin(server, { username: 'spyro', password: 'fake' }, 400)
+ const command = server.login
+ await command.login({ user: { username: 'spyro', password: 'spyro password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
+ await command.login({ user: { username: 'spyro', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should have disabled this auth', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredIdAndPassAuths
expect(auths).to.have.lengthOf(7)
})
it('Should uninstall the plugin one and do not login existing Crash', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-test-id-pass-auth-one'
- })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-id-pass-auth-one' })
- await userLogin(server, { username: 'crash', password: 'crash password' }, 400)
+ await server.login.login({
+ user: { username: 'crash', password: 'crash password' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
+ })
})
it('Should display the correct configuration', async function () {
- const res = await getConfig(server.url)
-
- const config: ServerConfig = res.body
+ const config = await server.config.getConfig()
const auths = config.plugin.registeredIdAndPassAuths
expect(auths).to.have.lengthOf(6)
})
it('Should display plugin auth information in users list', async function () {
- const res = await getUsersList(server.url, server.accessToken)
-
- const users: User[] = res.body.data
+ const { data } = await server.users.list()
- const root = users.find(u => u.username === 'root')
- const crash = users.find(u => u.username === 'crash')
- const laguna = users.find(u => u.username === 'laguna')
+ const root = data.find(u => u.username === 'root')
+ const crash = data.find(u => u.username === 'crash')
+ const laguna = data.find(u => u.username === 'laguna')
expect(root.pluginAuth).to.be.null
expect(crash.pluginAuth).to.equal('peertube-plugin-test-id-pass-auth-one')
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
+import { expect } from 'chai'
import {
checkVideoFilesWereRemoved,
+ cleanupTests,
+ createMultipleServers,
doubleFollow,
- getPluginTestPath,
- getVideo,
- installPlugin,
+ makeGetRequest,
makePostBodyRequest,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers,
- uploadVideoAndGetId,
- viewVideo,
- getVideosList,
- waitJobs,
- makeGetRequest
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
-import { expect } from 'chai'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+ waitJobs
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
-function postCommand (server: ServerInfo, command: string, bodyArg?: object) {
+function postCommand (server: PeerTubeServer, command: string, bodyArg?: object) {
const body = { command }
if (bodyArg) Object.assign(body, bodyArg)
url: server.url,
path: '/plugins/test-four/router/commander',
fields: body,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
})
}
describe('Test plugin helpers', function () {
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
before(async function () {
this.timeout(60000)
- servers = await flushAndRunMultipleServers(2)
+ servers = await createMultipleServers(2)
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
- await installPlugin({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- path: getPluginTestPath('-four')
- })
+ await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-four') })
})
describe('Logger', function () {
it('Should have logged things', async function () {
- await waitUntilLog(servers[0], 'localhost:' + servers[0].port + ' peertube-plugin-test-four', 1, false)
- await waitUntilLog(servers[0], 'Hello world from plugin four', 1)
+ await servers[0].servers.waitUntilLog('localhost:' + servers[0].port + ' peertube-plugin-test-four', 1, false)
+ await servers[0].servers.waitUntilLog('Hello world from plugin four', 1)
})
})
describe('Database', function () {
it('Should have made a query', async function () {
- await waitUntilLog(servers[0], `root email is admin${servers[0].internalServerNumber}@example.com`)
+ await servers[0].servers.waitUntilLog(`root email is admin${servers[0].internalServerNumber}@example.com`)
})
})
describe('Config', function () {
it('Should have the correct webserver url', async function () {
- await waitUntilLog(servers[0], `server url is http://localhost:${servers[0].port}`)
+ await servers[0].servers.waitUntilLog(`server url is http://localhost:${servers[0].port}`)
})
it('Should have the correct config', async function () {
const res = await makeGetRequest({
url: servers[0].url,
path: '/plugins/test-four/router/server-config',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.serverConfig).to.exist
describe('Server', function () {
it('Should get the server actor', async function () {
- await waitUntilLog(servers[0], 'server actor name is peertube')
+ await servers[0].servers.waitUntilLog('server actor name is peertube')
})
})
const res = await makeGetRequest({
url: servers[0].url,
path: '/plugins/test-four/router/static-route',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.staticRoute).to.equal('/plugins/test-four/0.0.1/static/')
const res = await makeGetRequest({
url: servers[0].url,
path: baseRouter + 'router-route',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.routerRoute).to.equal(baseRouter)
await makeGetRequest({
url: servers[0].url,
path: '/plugins/test-four/router/user',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
url: servers[0].url,
token: servers[0].accessToken,
path: '/plugins/test-four/router/user',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.username).to.equal('root')
this.timeout(60000)
{
- const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })
+ const res = await servers[0].videos.quickUpload({ name: 'video server 1' })
videoUUIDServer1 = res.uuid
}
{
- await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })
+ await servers[1].videos.quickUpload({ name: 'video server 2' })
}
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
- expect(videos).to.have.lengthOf(2)
+ expect(data).to.have.lengthOf(2)
})
it('Should mute server 2', async function () {
this.timeout(10000)
await postCommand(servers[0], 'blockServer', { hostToBlock: `localhost:${servers[1].port}` })
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('video server 1')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('video server 1')
})
it('Should unmute server 2', async function () {
await postCommand(servers[0], 'unblockServer', { hostToUnblock: `localhost:${servers[1].port}` })
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
- expect(videos).to.have.lengthOf(2)
+ expect(data).to.have.lengthOf(2)
})
it('Should mute account of server 2', async function () {
await postCommand(servers[0], 'blockAccount', { handleToBlock: `root@localhost:${servers[1].port}` })
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('video server 1')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('video server 1')
})
it('Should unmute account of server 2', async function () {
await postCommand(servers[0], 'unblockAccount', { handleToUnblock: `root@localhost:${servers[1].port}` })
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ const { data } = await servers[0].videos.list()
- expect(videos).to.have.lengthOf(2)
+ expect(data).to.have.lengthOf(2)
})
it('Should blacklist video', async function () {
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
+ const { data } = await server.videos.list()
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('video server 2')
+ expect(data).to.have.lengthOf(1)
+ expect(data[0].name).to.equal('video server 2')
}
})
await waitJobs(servers)
for (const server of servers) {
- const res = await getVideosList(server.url)
- const videos = res.body.data
+ const { data } = await server.videos.list()
- expect(videos).to.have.lengthOf(2)
+ expect(data).to.have.lengthOf(2)
}
})
})
let videoUUID: string
before(async () => {
- const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video1' })
+ const res = await servers[0].videos.quickUpload({ name: 'video1' })
videoUUID = res.uuid
})
this.timeout(40000)
// Should not throw -> video exists
- await getVideo(servers[0].url, videoUUID)
+ const video = await servers[0].videos.get({ id: videoUUID })
// Should delete the video
- await viewVideo(servers[0].url, videoUUID)
+ await servers[0].videos.view({ id: videoUUID })
- await waitUntilLog(servers[0], 'Video deleted by plugin four.')
+ await servers[0].servers.waitUntilLog('Video deleted by plugin four.')
try {
// Should throw because the video should have been deleted
- await getVideo(servers[0].url, videoUUID)
+ await servers[0].videos.get({ id: videoUUID })
throw new Error('Video exists')
} catch (err) {
if (err.message.includes('exists')) throw err
}
- await checkVideoFilesWereRemoved(videoUUID, servers[0].internalServerNumber)
+ await checkVideoFilesWereRemoved({ server: servers[0], video })
})
it('Should have fetched the video by URL', async function () {
- await waitUntilLog(servers[0], `video from DB uuid is ${videoUUID}`)
+ await servers[0].servers.waitUntilLog(`video from DB uuid is ${videoUUID}`)
})
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
+import { expect } from 'chai'
import {
- getPluginTestPath,
- installPlugin,
+ cleanupTests,
+ createSingleServer,
makeGetRequest,
makePostBodyRequest,
- setAccessTokensToServers, uninstallPlugin
-} from '../../../shared/extra-utils'
-import { expect } from 'chai'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+ PeerTubeServer,
+ PluginsCommand,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test plugin helpers', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
const basePaths = [
'/plugins/test-five/router/',
'/plugins/test-five/0.0.1/router/'
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-five')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-five') })
})
it('Should answer "pong"', async function () {
const res = await makeGetRequest({
url: server.url,
path: path + 'ping',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.message).to.equal('pong')
url: server.url,
path: path + 'is-authenticated',
token: server.accessToken,
- statusCodeExpected: 200
+ expectedStatus: 200
})
expect(res.body.isAuthenticated).to.equal(true)
const secRes = await makeGetRequest({
url: server.url,
path: path + 'is-authenticated',
- statusCodeExpected: 200
+ expectedStatus: 200
})
expect(secRes.body.isAuthenticated).to.equal(false)
url: server.url,
path: path + 'form/post/mirror',
fields: body,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body).to.deep.equal(body)
})
it('Should remove the plugin and remove the routes', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-test-five'
- })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-five' })
for (const path of basePaths) {
await makeGetRequest({
url: server.url,
path: path + 'ping',
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
await makePostBodyRequest({
url: server.url,
path: path + 'ping',
fields: {},
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
}
})
import { expect } from 'chai'
import { pathExists, readdir, readFile } from 'fs-extra'
import { join } from 'path'
-import { HttpStatusCode } from '@shared/core-utils'
import {
- buildServerDirectory,
- getPluginTestPath,
- installPlugin,
+ cleanupTests,
+ createSingleServer,
makeGetRequest,
- setAccessTokensToServers,
- uninstallPlugin
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
+ PeerTubeServer,
+ PluginsCommand,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test plugin storage', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-six')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-six') })
})
describe('DB storage', function () {
it('Should correctly store a subkey', async function () {
- await waitUntilLog(server, 'superkey stored value is toto')
+ await server.servers.waitUntilLog('superkey stored value is toto')
})
})
}
before(function () {
- dataPath = buildServerDirectory(server, 'plugins/data')
+ dataPath = server.servers.buildDirectory('plugins/data')
pluginDataPath = join(dataPath, 'peertube-plugin-test-six')
})
it('Should have created the directory on install', async function () {
- const dataPath = buildServerDirectory(server, 'plugins/data')
+ const dataPath = server.servers.buildDirectory('plugins/data')
const pluginDataPath = join(dataPath, 'peertube-plugin-test-six')
expect(await pathExists(dataPath)).to.be.true
url: server.url,
token: server.accessToken,
path: '/plugins/test-six/router/create-file',
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
const content = await getFileContent()
})
it('Should still have the file after an uninstallation', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-test-six'
- })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-six' })
const content = await getFileContent()
expect(content).to.equal('Prince Ali')
})
it('Should still have the file after the reinstallation', async function () {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-six')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-six') })
const content = await getFileContent()
expect(content).to.equal('Prince Ali')
import 'mocha'
import { expect } from 'chai'
-import { join } from 'path'
import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
-import { ServerConfig, VideoDetails, VideoPrivacy } from '@shared/models'
import {
- buildServerDirectory,
- createLive,
- getConfig,
- getPluginTestPath,
- getVideo,
- installPlugin,
- sendRTMPStreamInVideo,
+ cleanupTests,
+ createSingleServer,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers,
setDefaultVideoChannel,
testFfmpegStreamError,
- uninstallPlugin,
- updateCustomSubConfig,
- uploadVideoAndGetId,
- waitJobs,
- waitUntilLivePublished
-} from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
-
-async function createLiveWrapper (server: ServerInfo) {
+ waitJobs
+} from '@shared/extra-utils'
+import { VideoPrivacy } from '@shared/models'
+
+async function createLiveWrapper (server: PeerTubeServer) {
const liveAttributes = {
name: 'live video',
- channelId: server.videoChannel.id,
+ channelId: server.store.channel.id,
privacy: VideoPrivacy.PUBLIC
}
- const res = await createLive(server.url, server.accessToken, liveAttributes)
- return res.body.video.uuid
+ const { uuid } = await server.live.create({ fields: liveAttributes })
+
+ return uuid
}
-function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
- return updateCustomSubConfig(server.url, server.accessToken, {
- transcoding: {
- enabled: true,
- profile: vodProfile,
- hls: {
- enabled: true
- },
- webtorrent: {
- enabled: true
- },
- resolutions: {
- '240p': true,
- '360p': false,
- '480p': false,
- '720p': true
- }
- },
- live: {
+function updateConf (server: PeerTubeServer, vodProfile: string, liveProfile: string) {
+ return server.config.updateCustomSubConfig({
+ newConfig: {
transcoding: {
- profile: liveProfile,
enabled: true,
+ profile: vodProfile,
+ hls: {
+ enabled: true
+ },
+ webtorrent: {
+ enabled: true
+ },
resolutions: {
'240p': true,
'360p': false,
'480p': false,
'720p': true
}
+ },
+ live: {
+ transcoding: {
+ profile: liveProfile,
+ enabled: true,
+ resolutions: {
+ '240p': true,
+ '360p': false,
+ '480p': false,
+ '720p': true
+ }
+ }
}
}
})
}
describe('Test transcoding plugins', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(60000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
describe('When using a plugin adding profiles to existing encoders', function () {
async function checkVideoFPS (uuid: string, type: 'above' | 'below', fps: number) {
- const res = await getVideo(server.url, uuid)
- const video = res.body as VideoDetails
+ const video = await server.videos.get({ id: uuid })
const files = video.files.concat(...video.streamingPlaylists.map(p => p.files))
for (const file of files) {
}
before(async function () {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-transcoding-one')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
})
it('Should have the appropriate available profiles', async function () {
- const res = await getConfig(server.url)
- const config = res.body as ServerConfig
+ const config = await server.config.getConfig()
expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ])
- expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'low-live', 'input-options-live', 'bad-scale-live' ])
+ expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'high-live', 'input-options-live', 'bad-scale-live' ])
})
- it('Should not use the plugin profile if not chosen by the admin', async function () {
- this.timeout(240000)
+ describe('VOD', function () {
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
- await waitJobs([ server ])
+ it('Should not use the plugin profile if not chosen by the admin', async function () {
+ this.timeout(240000)
- await checkVideoFPS(videoUUID, 'above', 20)
- })
+ const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
+ await waitJobs([ server ])
- it('Should use the vod profile', async function () {
- this.timeout(240000)
+ await checkVideoFPS(videoUUID, 'above', 20)
+ })
- await updateConf(server, 'low-vod', 'default')
+ it('Should use the vod profile', async function () {
+ this.timeout(240000)
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
- await waitJobs([ server ])
+ await updateConf(server, 'low-vod', 'default')
- await checkVideoFPS(videoUUID, 'below', 12)
- })
+ const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
+ await waitJobs([ server ])
- it('Should apply input options in vod profile', async function () {
- this.timeout(240000)
+ await checkVideoFPS(videoUUID, 'below', 12)
+ })
- await updateConf(server, 'input-options-vod', 'default')
+ it('Should apply input options in vod profile', async function () {
+ this.timeout(240000)
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
- await waitJobs([ server ])
+ await updateConf(server, 'input-options-vod', 'default')
- await checkVideoFPS(videoUUID, 'below', 6)
- })
+ const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
+ await waitJobs([ server ])
- it('Should apply the scale filter in vod profile', async function () {
- this.timeout(240000)
+ await checkVideoFPS(videoUUID, 'below', 6)
+ })
- await updateConf(server, 'bad-scale-vod', 'default')
+ it('Should apply the scale filter in vod profile', async function () {
+ this.timeout(240000)
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
- await waitJobs([ server ])
+ await updateConf(server, 'bad-scale-vod', 'default')
- // Transcoding failed
- const res = await getVideo(server.url, videoUUID)
- const video: VideoDetails = res.body
+ const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
+ await waitJobs([ server ])
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
+ // Transcoding failed
+ const video = await server.videos.get({ id: videoUUID })
+ expect(video.files).to.have.lengthOf(1)
+ expect(video.streamingPlaylists).to.have.lengthOf(0)
+ })
})
- it('Should not use the plugin profile if not chosen by the admin', async function () {
- this.timeout(240000)
+ describe('Live', function () {
- const liveVideoId = await createLiveWrapper(server)
+ it('Should not use the plugin profile if not chosen by the admin', async function () {
+ this.timeout(240000)
- await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
- await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
- await waitJobs([ server ])
+ const liveVideoId = await createLiveWrapper(server)
- await checkLiveFPS(liveVideoId, 'above', 20)
- })
+ await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
+ await server.live.waitUntilPublished({ videoId: liveVideoId })
+ await waitJobs([ server ])
- it('Should use the live profile', async function () {
- this.timeout(240000)
+ await checkLiveFPS(liveVideoId, 'above', 20)
+ })
- await updateConf(server, 'low-vod', 'low-live')
+ it('Should use the live profile', async function () {
+ this.timeout(240000)
- const liveVideoId = await createLiveWrapper(server)
+ await updateConf(server, 'low-vod', 'high-live')
- await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
- await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
- await waitJobs([ server ])
+ const liveVideoId = await createLiveWrapper(server)
- await checkLiveFPS(liveVideoId, 'below', 12)
- })
+ await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
+ await server.live.waitUntilPublished({ videoId: liveVideoId })
+ await waitJobs([ server ])
- it('Should apply the input options on live profile', async function () {
- this.timeout(240000)
+ await checkLiveFPS(liveVideoId, 'above', 45)
+ })
- await updateConf(server, 'low-vod', 'input-options-live')
+ it('Should apply the input options on live profile', async function () {
+ this.timeout(240000)
- const liveVideoId = await createLiveWrapper(server)
+ await updateConf(server, 'low-vod', 'input-options-live')
- await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
- await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
- await waitJobs([ server ])
+ const liveVideoId = await createLiveWrapper(server)
- await checkLiveFPS(liveVideoId, 'below', 6)
- })
+ await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
+ await server.live.waitUntilPublished({ videoId: liveVideoId })
+ await waitJobs([ server ])
- it('Should apply the scale filter name on live profile', async function () {
- this.timeout(240000)
+ await checkLiveFPS(liveVideoId, 'above', 45)
+ })
- await updateConf(server, 'low-vod', 'bad-scale-live')
+ it('Should apply the scale filter name on live profile', async function () {
+ this.timeout(240000)
- const liveVideoId = await createLiveWrapper(server)
+ await updateConf(server, 'low-vod', 'bad-scale-live')
- const command = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
- await testFfmpegStreamError(command, true)
- })
+ const liveVideoId = await createLiveWrapper(server)
- it('Should default to the default profile if the specified profile does not exist', async function () {
- this.timeout(240000)
+ const command = await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
+ await testFfmpegStreamError(command, true)
+ })
- await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-test-transcoding-one' })
+ it('Should default to the default profile if the specified profile does not exist', async function () {
+ this.timeout(240000)
- const res = await getConfig(server.url)
- const config = res.body as ServerConfig
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
- expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
- expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
+ const config = await server.config.getConfig()
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
- await waitJobs([ server ])
+ expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
+ expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
+
+ const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
+ await waitJobs([ server ])
- await checkVideoFPS(videoUUID, 'above', 20)
+ await checkVideoFPS(videoUUID, 'above', 20)
+ })
})
})
describe('When using a plugin adding new encoders', function () {
before(async function () {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-transcoding-two')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
await updateConf(server, 'test-vod-profile', 'test-live-profile')
})
it('Should use the new vod encoders', async function () {
this.timeout(240000)
- const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video', fixture: 'video_short_240p.mp4' })).uuid
+ const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
await waitJobs([ server ])
- const path = buildServerDirectory(server, join('videos', videoUUID + '-240.mp4'))
+ const video = await server.videos.get({ id: videoUUID })
+
+ const path = server.servers.buildWebTorrentFilePath(video.files[0].fileUrl)
const audioProbe = await getAudioStream(path)
expect(audioProbe.audioStream.codec_name).to.equal('opus')
const liveVideoId = await createLiveWrapper(server)
- await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
- await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
+ await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
+ await server.live.waitUntilPublished({ videoId: liveVideoId })
await waitJobs([ server ])
const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
+import { expect } from 'chai'
import {
cleanupTests,
- flushAndRunServer,
- getPluginTestPath,
+ createSingleServer,
makeGetRequest,
- installPlugin,
- uninstallPlugin,
- ServerInfo,
+ PeerTubeServer,
+ PluginsCommand,
setAccessTokensToServers
-} from '../../../shared/extra-utils'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { expect } from 'chai'
+} from '@shared/extra-utils'
+import { HttpStatusCode } from '@shared/models'
describe('Test plugins module unloading', function () {
- let server: ServerInfo = null
+ let server: PeerTubeServer = null
const requestPath = '/plugins/test-unloading/router/get'
let value: string = null
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-unloading')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-unloading') })
})
it('Should return a numeric value', async function () {
const res = await makeGetRequest({
url: server.url,
path: requestPath,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.message).to.match(/^\d+$/)
const res = await makeGetRequest({
url: server.url,
path: requestPath,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.message).to.be.equal(value)
})
it('Should uninstall the plugin and free the route', async function () {
- await uninstallPlugin({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-test-unloading'
- })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-unloading' })
await makeGetRequest({
url: server.url,
path: requestPath,
- statusCodeExpected: HttpStatusCode.NOT_FOUND_404
+ expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
it('Should return a different numeric value', async function () {
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-unloading')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-unloading') })
+
const res = await makeGetRequest({
url: server.url,
path: requestPath,
- statusCodeExpected: HttpStatusCode.OK_200
+ expectedStatus: HttpStatusCode.OK_200
})
expect(res.body.message).to.match(/^\d+$/)
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
-import {
- getPluginTestPath,
- getPluginTranslations,
- installPlugin,
- setAccessTokensToServers,
- uninstallPlugin
-} from '../../../shared/extra-utils'
+import * as chai from 'chai'
+import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers } from '@shared/extra-utils'
const expect = chai.expect
describe('Test plugin translations', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
+ let command: PluginsCommand
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath()
- })
+ command = server.plugins
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-filter-translations')
- })
+ await command.install({ path: PluginsCommand.getPluginTestPath() })
+ await command.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
})
it('Should not have translations for locale pt', async function () {
- const res = await getPluginTranslations({ url: server.url, locale: 'pt' })
+ const body = await command.getTranslations({ locale: 'pt' })
- expect(res.body).to.deep.equal({})
+ expect(body).to.deep.equal({})
})
it('Should have translations for locale fr', async function () {
- const res = await getPluginTranslations({ url: server.url, locale: 'fr-FR' })
+ const body = await command.getTranslations({ locale: 'fr-FR' })
- expect(res.body).to.deep.equal({
+ expect(body).to.deep.equal({
'peertube-plugin-test': {
Hi: 'Coucou'
},
})
it('Should have translations of locale it', async function () {
- const res = await getPluginTranslations({ url: server.url, locale: 'it-IT' })
+ const body = await command.getTranslations({ locale: 'it-IT' })
- expect(res.body).to.deep.equal({
+ expect(body).to.deep.equal({
'peertube-plugin-test-filter-translations': {
'Hello world': 'Ciao, mondo!'
}
})
it('Should remove the plugin and remove the locales', async function () {
- await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-test-filter-translations' })
+ await command.uninstall({ npmName: 'peertube-plugin-test-filter-translations' })
{
- const res = await getPluginTranslations({ url: server.url, locale: 'fr-FR' })
+ const body = await command.getTranslations({ locale: 'fr-FR' })
- expect(res.body).to.deep.equal({
+ expect(body).to.deep.equal({
'peertube-plugin-test': {
Hi: 'Coucou'
}
}
{
- const res = await getPluginTranslations({ url: server.url, locale: 'it-IT' })
+ const body = await command.getTranslations({ locale: 'it-IT' })
- expect(res.body).to.deep.equal({})
+ expect(body).to.deep.equal({})
}
})
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import * as chai from 'chai'
import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
+import * as chai from 'chai'
import {
- createVideoPlaylist,
- getPluginTestPath,
- getVideo,
- getVideoCategories,
- getVideoLanguages,
- getVideoLicences, getVideoPlaylistPrivacies, getVideoPrivacies,
- installPlugin,
- setAccessTokensToServers,
- uninstallPlugin,
- uploadVideo
-} from '../../../shared/extra-utils'
-import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+ cleanupTests,
+ createSingleServer,
+ makeGetRequest,
+ PeerTubeServer,
+ PluginsCommand,
+ setAccessTokensToServers
+} from '@shared/extra-utils'
+import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
const expect = chai.expect
describe('Test plugin altering video constants', function () {
- let server: ServerInfo
+ let server: PeerTubeServer
before(async function () {
this.timeout(30000)
- server = await flushAndRunServer(1)
+ server = await createSingleServer(1)
await setAccessTokensToServers([ server ])
- await installPlugin({
- url: server.url,
- accessToken: server.accessToken,
- path: getPluginTestPath('-video-constants')
- })
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-video-constants') })
})
it('Should have updated languages', async function () {
- const res = await getVideoLanguages(server.url)
- const languages = res.body
+ const languages = await server.videos.getLanguages()
expect(languages['en']).to.not.exist
expect(languages['fr']).to.not.exist
})
it('Should have updated categories', async function () {
- const res = await getVideoCategories(server.url)
- const categories = res.body
+ const categories = await server.videos.getCategories()
expect(categories[1]).to.not.exist
expect(categories[2]).to.not.exist
})
it('Should have updated licences', async function () {
- const res = await getVideoLicences(server.url)
- const licences = res.body
+ const licences = await server.videos.getLicences()
expect(licences[1]).to.not.exist
expect(licences[7]).to.not.exist
})
it('Should have updated video privacies', async function () {
- const res = await getVideoPrivacies(server.url)
- const privacies = res.body
+ const privacies = await server.videos.getPrivacies()
expect(privacies[1]).to.exist
expect(privacies[2]).to.not.exist
})
it('Should have updated playlist privacies', async function () {
- const res = await getVideoPlaylistPrivacies(server.url)
- const playlistPrivacies = res.body
+ const playlistPrivacies = await server.playlists.getPrivacies()
expect(playlistPrivacies[1]).to.exist
expect(playlistPrivacies[2]).to.exist
})
it('Should not be able to create a video with this privacy', async function () {
- const attrs = { name: 'video', privacy: 2 }
- await uploadVideo(server.url, server.accessToken, attrs, HttpStatusCode.BAD_REQUEST_400)
+ const attributes = { name: 'video', privacy: 2 }
+ await server.videos.upload({ attributes, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should not be able to create a video with this privacy', async function () {
- const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
- await createVideoPlaylist({
- url: server.url,
- token: server.accessToken,
- playlistAttrs: attrs,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
+ const attributes = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
+ await server.playlists.create({ attributes, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
})
it('Should be able to upload a video with these values', async function () {
- const attrs = { name: 'video', category: 42, licence: 42, language: 'al_bhed2' }
- const resUpload = await uploadVideo(server.url, server.accessToken, attrs)
+ const attributes = { name: 'video', category: 42, licence: 42, language: 'al_bhed2' }
+ const { uuid } = await server.videos.upload({ attributes })
- const res = await getVideo(server.url, resUpload.body.video.uuid)
-
- const video: VideoDetails = res.body
+ const video = await server.videos.get({ id: uuid })
expect(video.language.label).to.equal('Al Bhed 2')
expect(video.licence.label).to.equal('Best licence')
expect(video.category.label).to.equal('Best category')
})
it('Should uninstall the plugin and reset languages, categories, licences and privacies', async function () {
- await uninstallPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-test-video-constants' })
+ await server.plugins.uninstall({ npmName: 'peertube-plugin-test-video-constants' })
{
- const res = await getVideoLanguages(server.url)
- const languages = res.body
+ const languages = await server.videos.getLanguages()
expect(languages['en']).to.equal('English')
expect(languages['fr']).to.equal('French')
}
{
- const res = await getVideoCategories(server.url)
- const categories = res.body
+ const categories = await server.videos.getCategories()
expect(categories[1]).to.equal('Music')
expect(categories[2]).to.equal('Films')
}
{
- const res = await getVideoLicences(server.url)
- const licences = res.body
+ const licences = await server.videos.getLicences()
expect(licences[1]).to.equal('Attribution')
expect(licences[7]).to.equal('Public Domain Dedication')
}
{
- const res = await getVideoPrivacies(server.url)
- const privacies = res.body
+ const privacies = await server.videos.getPrivacies()
expect(privacies[1]).to.exist
expect(privacies[2]).to.exist
}
{
- const res = await getVideoPlaylistPrivacies(server.url)
- const playlistPrivacies = res.body
+ const playlistPrivacies = await server.playlists.getPrivacies()
expect(playlistPrivacies[1]).to.exist
expect(playlistPrivacies[2]).to.exist
}
})
+ it('Should be able to reset categories', async function () {
+ await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-video-constants') })
+
+ {
+ const categories = await server.videos.getCategories()
+
+ expect(categories[1]).to.not.exist
+ expect(categories[2]).to.not.exist
+
+ expect(categories[42]).to.exist
+ expect(categories[43]).to.exist
+ }
+
+ await makeGetRequest({
+ url: server.url,
+ token: server.accessToken,
+ path: '/plugins/test-video-constants/router/reset-categories',
+ expectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+
+ {
+ const categories = await server.videos.getCategories()
+
+ expect(categories[1]).to.exist
+ expect(categories[2]).to.exist
+
+ expect(categories[42]).to.not.exist
+ expect(categories[43]).to.not.exist
+ }
+ })
+
after(async function () {
await cleanupTests([ server ])
})
+import { Command } from 'commander'
import { Netrc } from 'netrc-parser'
-import { getAppNumber, isTestInstance } from '../helpers/core-utils'
import { join } from 'path'
-import { root } from '../../shared/extra-utils/miscs/miscs'
-import { getVideoChannel } from '../../shared/extra-utils/videos/video-channels'
-import { VideoChannel, VideoPrivacy } from '../../shared/models/videos'
import { createLogger, format, transports } from 'winston'
-import { getMyUserInformation } from '@shared/extra-utils/users/users'
-import { User, UserRole } from '@shared/models'
-import { getAccessToken } from '@shared/extra-utils/users/login'
-import { Command } from 'commander'
+import { PeerTubeServer } from '@shared/extra-utils'
+import { UserRole } from '@shared/models'
+import { VideoPrivacy } from '../../shared/models/videos'
+import { getAppNumber, isTestInstance, root } from '../helpers/core-utils'
let configName = 'PeerTube/CLI'
if (isTestInstance()) configName += `-${getAppNumber()}`
const version = require('../../../package.json').version
-async function getAdminTokenOrDie (url: string, username: string, password: string) {
- const accessToken = await getAccessToken(url, username, password)
- const resMe = await getMyUserInformation(url, accessToken)
- const me: User = resMe.body
+async function getAdminTokenOrDie (server: PeerTubeServer, username: string, password: string) {
+ const token = await server.login.getAccessToken(username, password)
+ const me = await server.users.getMyInfo({ token })
if (me.role !== UserRole.ADMINISTRATOR) {
console.error('You must be an administrator.')
process.exit(-1)
}
- return accessToken
+ return token
}
interface Settings {
.option('-v, --verbose <verbose>', 'Verbosity, from 0/\'error\' to 4/\'debug\'', 'info')
}
-async function buildVideoAttributesFromCommander (url: string, command: Command, defaultAttributes: any = {}) {
+async function buildVideoAttributesFromCommander (server: PeerTubeServer, command: Command, defaultAttributes: any = {}) {
const options = command.opts()
const defaultBooleanAttributes = {
Object.assign(videoAttributes, booleanAttributes)
if (options.channelName) {
- const res = await getVideoChannel(url, options.channelName)
- const videoChannel: VideoChannel = res.body
+ const videoChannel = await server.channels.get({ channelName: options.channelName })
Object.assign(videoAttributes, { channelId: videoChannel.id })
})
}
+function buildServer (url: string) {
+ return new PeerTubeServer({ url })
+}
+
+async function assignToken (server: PeerTubeServer, username: string, password: string) {
+ const bodyClient = await server.login.getClient()
+ const client = { id: bodyClient.client_id, secret: bodyClient.client_secret }
+
+ const body = await server.login.login({ client, user: { username, password } })
+
+ server.accessToken = body.access_token
+}
+
function getLogger (logLevel = 'info') {
const logLevels = {
0: 0,
buildCommonVideoOptions,
buildVideoAttributesFromCommander,
- getAdminTokenOrDie
+ getAdminTokenOrDie,
+ buildServer,
+ assignToken
}
import { OptionValues, program } from 'commander'
import * as prompt from 'prompt'
-import { getNetrc, getSettings, writeSettings } from './cli'
+import { assignToken, buildServer, getNetrc, getSettings, writeSettings } from './cli'
import { isUserUsernameValid } from '../helpers/custom-validators/users'
-import { getAccessToken } from '../../shared/extra-utils'
import * as CliTable3 from 'cli-table3'
async function delInstance (url: string) {
// @see https://github.com/Chocobozzz/PeerTube/issues/3520
result.url = stripExtraneousFromPeerTubeUrl(result.url)
- await getAccessToken(result.url, result.username, result.password)
+ const server = buildServer(result.url)
+ await assignToken(server, result.username, result.password)
} catch (err) {
console.error(err.message)
process.exit(-1)
registerTSPaths()
import { program } from 'commander'
-import { getClient, Server, serverLogin } from '../../shared/extra-utils'
+import { assignToken, buildServer } from './cli'
program
.option('-u, --url <url>', 'Server url')
process.exit(-1)
}
-getClient(options.url)
- .then(res => {
- const server = {
- url: options.url,
- user: {
- username: options.username,
- password: options.password
- },
- client: {
- id: res.body.client_id,
- secret: res.body.client_secret
- }
- } as Server
+const server = buildServer(options.url)
- return serverLogin(server)
- })
- .then(accessToken => {
- console.log(accessToken)
+assignToken(server, options.username, options.password)
+ .then(() => {
+ console.log(server.accessToken)
process.exit(0)
})
.catch(err => {
import { join } from 'path'
import * as prompt from 'prompt'
import { promisify } from 'util'
-import { advancedVideosSearch, getClient, getVideoCategories, login, uploadVideo } from '../../shared/extra-utils/index'
+import { YoutubeDL } from '@server/helpers/youtube-dl'
import { sha256 } from '../helpers/core-utils'
import { doRequestAndSaveToFile } from '../helpers/requests'
import { CONSTRAINTS_FIELDS } from '../initializers/constants'
-import { buildCommonVideoOptions, buildVideoAttributesFromCommander, getLogger, getServerCredentials } from './cli'
-import { YoutubeDL } from '@server/helpers/youtube-dl'
-
-type UserInfo = {
- username: string
- password: string
-}
+import {
+ assignToken,
+ buildCommonVideoOptions,
+ buildServer,
+ buildVideoAttributesFromCommander,
+ getLogger,
+ getServerCredentials
+} from './cli'
+import { PeerTubeServer } from '@shared/extra-utils'
const processOptions = {
maxBuffer: Infinity
url = normalizeTargetUrl(url)
options.targetUrl = normalizeTargetUrl(options.targetUrl)
- const user = { username, password }
-
- run(url, user)
+ run(url, username, password)
.catch(err => exitError(err))
})
.catch(err => console.error(err))
-async function run (url: string, user: UserInfo) {
- if (!user.password) {
- user.password = await promptPassword()
- }
+async function run (url: string, username: string, password: string) {
+ if (!password) password = await promptPassword()
const youtubeDLBinary = await YoutubeDL.safeGetYoutubeDL()
await processVideo({
cwd: options.tmpdir,
url,
- user,
+ username,
+ password,
youtubeInfo: info
})
} catch (err) {
}
}
- log.info('Video/s for user %s imported: %s', user.username, options.targetUrl)
+ log.info('Video/s for user %s imported: %s', username, options.targetUrl)
process.exit(0)
}
async function processVideo (parameters: {
cwd: string
url: string
- user: { username: string, password: string }
+ username: string
+ password: string
youtubeInfo: any
}) {
- const { youtubeInfo, cwd, url, user } = parameters
+ const { youtubeInfo, cwd, url, username, password } = parameters
const youtubeDL = new YoutubeDL('', [])
log.debug('Fetching object.', youtubeInfo)
log.debug('Fetched object.', videoInfo)
const originallyPublishedAt = youtubeDL.buildOriginallyPublishedAt(videoInfo)
+
if (options.since && originallyPublishedAt && originallyPublishedAt.getTime() < options.since.getTime()) {
- log.info('Video "%s" has been published before "%s", don\'t upload it.\n',
- videoInfo.title, formatDate(options.since))
+ log.info('Video "%s" has been published before "%s", don\'t upload it.\n', videoInfo.title, formatDate(options.since))
return
}
+
if (options.until && originallyPublishedAt && originallyPublishedAt.getTime() > options.until.getTime()) {
- log.info('Video "%s" has been published after "%s", don\'t upload it.\n',
- videoInfo.title, formatDate(options.until))
+ log.info('Video "%s" has been published after "%s", don\'t upload it.\n', videoInfo.title, formatDate(options.until))
return
}
- const result = await advancedVideosSearch(url, { search: videoInfo.title, sort: '-match', searchTarget: 'local' })
+ const server = buildServer(url)
+ const { data } = await server.search.advancedVideoSearch({
+ search: {
+ search: videoInfo.title,
+ sort: '-match',
+ searchTarget: 'local'
+ }
+ })
log.info('############################################################\n')
- if (result.body.data.find(v => v.name === videoInfo.title)) {
+ if (data.find(v => v.name === videoInfo.title)) {
log.info('Video "%s" already exists, don\'t reupload it.\n', videoInfo.title)
return
}
youtubeDL,
cwd,
url,
- user,
+ username,
+ password,
videoInfo: normalizeObject(videoInfo),
videoPath: path
})
videoPath: string
cwd: string
url: string
- user: { username: string, password: string }
+ username: string
+ password: string
}) {
- const { youtubeDL, videoInfo, videoPath, cwd, url, user } = parameters
+ const { youtubeDL, videoInfo, videoPath, cwd, url, username, password } = parameters
- const category = await getCategory(videoInfo.categories, url)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
+
+ const category = await getCategory(server, videoInfo.categories)
const licence = getLicence(videoInfo.license)
let tags = []
if (Array.isArray(videoInfo.tags)) {
tags
}
- const videoAttributes = await buildVideoAttributesFromCommander(url, program, defaultAttributes)
+ const baseAttributes = await buildVideoAttributesFromCommander(server, program, defaultAttributes)
+
+ const attributes = {
+ ...baseAttributes,
- Object.assign(videoAttributes, {
originallyPublishedAt: originallyPublishedAt ? originallyPublishedAt.toISOString() : null,
thumbnailfile,
previewfile: thumbnailfile,
fixture: videoPath
- })
-
- log.info('\nUploading on PeerTube video "%s".', videoAttributes.name)
+ }
- let accessToken = await getAccessTokenOrDie(url, user)
+ log.info('\nUploading on PeerTube video "%s".', attributes.name)
try {
- await uploadVideo(url, accessToken, videoAttributes)
+ await server.videos.upload({ attributes })
} catch (err) {
if (err.message.indexOf('401') !== -1) {
log.info('Got 401 Unauthorized, token may have expired, renewing token and retry.')
- accessToken = await getAccessTokenOrDie(url, user)
+ server.accessToken = await server.login.getAccessToken(username, password)
- await uploadVideo(url, accessToken, videoAttributes)
+ await server.videos.upload({ attributes })
} else {
exitError(err.message)
}
await remove(videoPath)
if (thumbnailfile) await remove(thumbnailfile)
- log.warn('Uploaded video "%s"!\n', videoAttributes.name)
+ log.warn('Uploaded video "%s"!\n', attributes.name)
}
/* ---------------------------------------------------------- */
-async function getCategory (categories: string[], url: string) {
+async function getCategory (server: PeerTubeServer, categories: string[]) {
if (!categories) return undefined
const categoryString = categories[0]
if (categoryString === 'News & Politics') return 11
- const res = await getVideoCategories(url)
- const categoriesServer = res.body
+ const categoriesServer = await server.videos.getCategories()
for (const key of Object.keys(categoriesServer)) {
const categoryServer = categoriesServer[key]
})
}
-async function getAccessTokenOrDie (url: string, user: UserInfo) {
- const resClient = await getClient(url)
- const client = {
- id: resClient.body.client_id,
- secret: resClient.body.client_secret
- }
-
- try {
- const res = await login(url, client, user)
- return res.body.access_token
- } catch (err) {
- exitError('Cannot authenticate. Please check your username/password.')
- }
-}
-
function parseDate (dateAsStr: string): Date {
if (!/\d{4}-\d{2}-\d{2}/.test(dateAsStr)) {
exitError(`Invalid date passed: ${dateAsStr}. Expected format: YYYY-MM-DD. See help for usage.`)
registerTSPaths()
import { program, Command, OptionValues } from 'commander'
-import { installPlugin, listPlugins, uninstallPlugin, updatePlugin } from '../../shared/extra-utils/server/plugins'
-import { getAdminTokenOrDie, getServerCredentials } from './cli'
-import { PeerTubePlugin, PluginType } from '../../shared/models'
+import { assignToken, buildServer, getServerCredentials } from './cli'
+import { PluginType } from '../../shared/models'
import { isAbsolute } from 'path'
import * as CliTable3 from 'cli-table3'
async function pluginsListCLI (command: Command, options: OptionValues) {
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
let pluginType: PluginType
if (options.onlyThemes) pluginType = PluginType.THEME
if (options.onlyPlugins) pluginType = PluginType.PLUGIN
- const res = await listPlugins({
- url,
- accessToken,
- start: 0,
- count: 100,
- sort: 'name',
- pluginType
- })
- const plugins: PeerTubePlugin[] = res.body.data
+ const { data } = await server.plugins.list({ start: 0, count: 100, sort: 'name', pluginType })
const table = new CliTable3({
head: [ 'name', 'version', 'homepage' ],
colWidths: [ 50, 10, 50 ]
}) as any
- for (const plugin of plugins) {
+ for (const plugin of data) {
const npmName = plugin.type === PluginType.PLUGIN
? 'peertube-plugin-' + plugin.name
: 'peertube-theme-' + plugin.name
}
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
try {
- await installPlugin({
- url,
- accessToken,
- npmName: options.npmName,
- path: options.path
- })
+ await server.plugins.install({ npmName: options.npmName, path: options.path })
} catch (err) {
console.error('Cannot install plugin.', err)
process.exit(-1)
}
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
try {
- await updatePlugin({
- url,
- accessToken,
- npmName: options.npmName,
- path: options.path
- })
+ await server.plugins.update({ npmName: options.npmName, path: options.path })
} catch (err) {
console.error('Cannot update plugin.', err)
process.exit(-1)
}
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
try {
- await uninstallPlugin({
- url,
- accessToken,
- npmName: options.npmName
- })
+ await server.plugins.uninstall({ npmName: options.npmName })
} catch (err) {
console.error('Cannot uninstall plugin.', err)
process.exit(-1)
-// eslint-disable @typescript-eslint/no-unnecessary-type-assertion
-
import { registerTSPaths } from '../helpers/register-ts-paths'
registerTSPaths()
-import { program, Command } from 'commander'
-import { getAdminTokenOrDie, getServerCredentials } from './cli'
-import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
-import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
-import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
-import validator from 'validator'
import * as CliTable3 from 'cli-table3'
-import { URL } from 'url'
+import { Command, program } from 'commander'
import { uniq } from 'lodash'
+import { URL } from 'url'
+import validator from 'validator'
+import { HttpStatusCode, VideoRedundanciesTarget } from '@shared/models'
+import { assignToken, buildServer, getServerCredentials } from './cli'
import bytes = require('bytes')
async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
const { url, username, password } = await getServerCredentials(program)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
- const redundancies = await listVideoRedundanciesData(url, accessToken, target)
+ const { data } = await server.redundancy.listVideos({ start: 0, count: 100, sort: 'name', target })
const table = new CliTable3({
head: [ 'video id', 'video name', 'video url', 'files', 'playlists', 'by instances', 'total size' ]
}) as any
- for (const redundancy of redundancies) {
+ for (const redundancy of data) {
const webtorrentFiles = redundancy.redundancies.files
const streamingPlaylists = redundancy.redundancies.streamingPlaylists
async function addRedundancyCLI (options: { video: number }, command: Command) {
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
if (!options.video || validator.isInt('' + options.video) === false) {
console.error('You need to specify the video id to duplicate and it should be a number.\n')
}
try {
- await addVideoRedundancy({
- url,
- accessToken,
- videoId: options.video
- })
+ await server.redundancy.addVideo({ videoId: options.video })
console.log('Video will be duplicated by your instance!')
async function removeRedundancyCLI (options: { video: number }, command: Command) {
const { url, username, password } = await getServerCredentials(command)
- const accessToken = await getAdminTokenOrDie(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
if (!options.video || validator.isInt('' + options.video) === false) {
console.error('You need to specify the video id to remove from your redundancies.\n')
const videoId = parseInt(options.video + '', 10)
- let redundancies = await listVideoRedundanciesData(url, accessToken, 'my-videos')
- let videoRedundancy = redundancies.find(r => videoId === r.id)
+ const myVideoRedundancies = await server.redundancy.listVideos({ target: 'my-videos' })
+ let videoRedundancy = myVideoRedundancies.data.find(r => videoId === r.id)
if (!videoRedundancy) {
- redundancies = await listVideoRedundanciesData(url, accessToken, 'remote-videos')
- videoRedundancy = redundancies.find(r => videoId === r.id)
+ const remoteVideoRedundancies = await server.redundancy.listVideos({ target: 'remote-videos' })
+ videoRedundancy = remoteVideoRedundancies.data.find(r => videoId === r.id)
}
if (!videoRedundancy) {
.map(r => r.id)
for (const id of ids) {
- await removeVideoRedundancy({
- url,
- accessToken,
- redundancyId: id
- })
+ await server.redundancy.removeVideo({ redundancyId: id })
}
console.log('Video redundancy removed!')
process.exit(-1)
}
}
-
-async function listVideoRedundanciesData (url: string, accessToken: string, target: VideoRedundanciesTarget) {
- const res = await listVideoRedundancies({
- url,
- accessToken,
- start: 0,
- count: 100,
- sort: 'name',
- target
- })
-
- return res.body.data as VideoRedundancy[]
-}
import { program } from 'commander'
import { access, constants } from 'fs-extra'
import { isAbsolute } from 'path'
-import { getAccessToken } from '../../shared/extra-utils'
-import { uploadVideo } from '../../shared/extra-utils/'
-import { buildCommonVideoOptions, buildVideoAttributesFromCommander, getServerCredentials } from './cli'
+import { assignToken, buildCommonVideoOptions, buildServer, buildVideoAttributesFromCommander, getServerCredentials } from './cli'
let command = program
.name('upload')
.catch(err => console.error(err))
async function run (url: string, username: string, password: string) {
- const accessToken = await getAccessToken(url, username, password)
+ const server = buildServer(url)
+ await assignToken(server, username, password)
await access(options.file, constants.F_OK)
console.log('Uploading %s video...', options.videoName)
- const videoAttributes = await buildVideoAttributesFromCommander(url, program)
+ const baseAttributes = await buildVideoAttributesFromCommander(server, program)
+
+ const attributes = {
+ ...baseAttributes,
- Object.assign(videoAttributes, {
fixture: options.file,
thumbnailfile: options.thumbnail,
previewfile: options.preview
- })
+ }
try {
- await uploadVideo(url, accessToken, videoAttributes)
+ await server.videos.upload({ attributes })
console.log(`Video ${options.videoName} uploaded.`)
process.exit(0)
} catch (err) {
-import { registerTSPaths } from '../helpers/register-ts-paths'
-registerTSPaths()
-
-import { LiveVideo, LiveVideoCreate, VideoPrivacy } from '@shared/models'
import { program } from 'commander'
+import { LiveVideoCreate, VideoPrivacy } from '@shared/models'
import {
- createLive,
- flushAndRunServer,
- getLive,
+ createSingleServer,
killallServers,
sendRTMPStream,
- ServerInfo,
+ PeerTubeServer,
setAccessTokensToServers,
- setDefaultVideoChannel,
- updateCustomSubConfig
+ setDefaultVideoChannel
} from '../../shared/extra-utils'
+import { registerTSPaths } from '../helpers/register-ts-paths'
+
+registerTSPaths()
type CommandType = 'live-mux' | 'live-transcoding'
registerTSPaths()
const command = program
- .name('test')
+ .name('test-live')
.option('-t, --type <type>', 'live-muxing|live-transcoding')
.parse(process.argv)
console.log('Starting server.')
- const server = await flushAndRunServer(1, {}, [], { hideLogs: false, execArgv: [ '--inspect' ] })
+ const server = await createSingleServer(1, {}, { hideLogs: false, nodeArgs: [ '--inspect' ] })
- const cleanup = () => {
+ const cleanup = async () => {
console.log('Killing server')
- killallServers([ server ])
+ await killallServers([ server ])
}
process.on('exit', cleanup)
const attributes: LiveVideoCreate = {
name: 'live',
saveReplay: true,
- channelId: server.videoChannel.id,
+ channelId: server.store.channel.id,
privacy: VideoPrivacy.PUBLIC
}
console.log('Creating live.')
- const res = await createLive(server.url, server.accessToken, attributes)
- const liveVideoUUID = res.body.video.uuid
+ const { uuid: liveVideoUUID } = await server.live.create({ fields: attributes })
- const resLive = await getLive(server.url, server.accessToken, liveVideoUUID)
- const live: LiveVideo = resLive.body
+ const live = await server.live.get({ videoId: liveVideoUUID })
console.log('Sending RTMP stream.')
// ----------------------------------------------------------------------------
-async function buildConfig (server: ServerInfo, commandType: CommandType) {
- await updateCustomSubConfig(server.url, server.accessToken, {
- instance: {
- customizations: {
- javascript: '',
- css: ''
- }
- },
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: commandType === 'live-transcoding'
+async function buildConfig (server: PeerTubeServer, commandType: CommandType) {
+ await server.config.updateCustomSubConfig({
+ newConfig: {
+ instance: {
+ customizations: {
+ javascript: '',
+ css: ''
+ }
+ },
+ live: {
+ enabled: true,
+ allowReplay: true,
+ transcoding: {
+ enabled: commandType === 'live-transcoding'
+ }
}
}
})
PickWithOpt<VideoStreamingPlaylistModel, 'RedundancyVideos', MVideoRedundancyFileUrl[]>
export function isStreamingPlaylist (value: MVideo | MStreamingPlaylistVideo): value is MStreamingPlaylistVideo {
- return !!(value as MStreamingPlaylist).playlistUrl
+ return !!(value as MStreamingPlaylist).videoId
}
+import { OutgoingHttpHeaders } from 'http'
import { RegisterServerAuthExternalOptions } from '@server/types'
import {
MAbuseMessage,
import { MVideoImportDefault } from '@server/types/models/video/video-import'
import { MVideoPlaylistElement, MVideoPlaylistElementVideoUrlPlaylistPrivacy } from '@server/types/models/video/video-playlist-element'
import { MAccountVideoRateAccountVideo } from '@server/types/models/video/video-rate'
-import { HttpMethod } from '@shared/core-utils/miscs/http-methods'
-import { PeerTubeProblemDocumentData, ServerErrorCode, VideoCreate } from '@shared/models'
+import { HttpMethod, PeerTubeProblemDocumentData, ServerErrorCode, VideoCreate } from '@shared/models'
import { File as UploadXFile, Metadata } from '@uploadx/core'
import { RegisteredPlugin } from '../../lib/plugins/plugin-manager'
import {
MVideoShareActor,
MVideoThumbnail
} from '../../types/models'
+import { Writable } from 'stream'
declare module 'express' {
export interface Request {
}) => void
locals: {
+ apicache: {
+ content: string | Buffer
+ write: Writable['write']
+ writeHead: Response['writeHead']
+ end: Response['end']
+ cacheable: boolean
+ headers: OutgoingHttpHeaders
+ }
+
docUrl?: string
videoAPI?: MVideoFormattableDetails
return getDaysDifferences(now, d) <= 7
}
+function timeToInt (time: number | string) {
+ if (!time) return 0
+ if (typeof time === 'number') return time
+
+ const reg = /^((\d+)[h:])?((\d+)[m:])?((\d+)s?)?$/
+ const matches = time.match(reg)
+
+ if (!matches) return 0
+
+ const hours = parseInt(matches[2] || '0', 10)
+ const minutes = parseInt(matches[4] || '0', 10)
+ const seconds = parseInt(matches[6] || '0', 10)
+
+ return hours * 3600 + minutes * 60 + seconds
+}
+
+function secondsToTime (seconds: number, full = false, symbol?: string) {
+ let time = ''
+
+ if (seconds === 0 && !full) return '0s'
+
+ const hourSymbol = (symbol || 'h')
+ const minuteSymbol = (symbol || 'm')
+ const secondsSymbol = full ? '' : 's'
+
+ const hours = Math.floor(seconds / 3600)
+ if (hours >= 1) time = hours + hourSymbol
+ else if (full) time = '0' + hourSymbol
+
+ seconds %= 3600
+ const minutes = Math.floor(seconds / 60)
+ if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol
+ else if (minutes >= 1) time += minutes + minuteSymbol
+ else if (full) time += '00' + minuteSymbol
+
+ seconds %= 60
+ if (seconds >= 1 && seconds < 10 && full) time += '0' + seconds + secondsSymbol
+ else if (seconds >= 1) time += seconds + secondsSymbol
+ else if (full) time += '00'
+
+ return time
+}
+
// ---------------------------------------------------------------------------
export {
isThisMonth,
isToday,
isLastMonth,
- isLastWeek
+ isLastWeek,
+ timeToInt,
+ secondsToTime
}
// ---------------------------------------------------------------------------
--- /dev/null
+export * from './date'
+export * from './miscs'
+export * from './regexp'
+export * from './promises'
+export * from './types'
+export * from './url'
return segmentsA.length - segmentsB.length
}
-function isPromise (value: any) {
- return value && typeof value.then === 'function'
-}
-
-function isCatchable (value: any) {
- return value && typeof value.catch === 'function'
-}
-
function sortObjectComparator (key: string, order: 'asc' | 'desc') {
return (a: any, b: any) => {
if (a[key] < b[key]) {
export {
randomInt,
compareSemVer,
- isPromise,
- isCatchable,
sortObjectComparator
}
--- /dev/null
+function isPromise (value: any) {
+ return value && typeof value.then === 'function'
+}
+
+function isCatchable (value: any) {
+ return value && typeof value.catch === 'function'
+}
+
+export {
+ isPromise,
+ isCatchable
+}
--- /dev/null
+export const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
+
+export function removeFragmentedMP4Ext (path: string) {
+ return path.replace(/-fragmented.mp4$/i, '')
+}
--- /dev/null
+import { Video, VideoPlaylist } from '../../models'
+import { secondsToTime } from './date'
+
+function buildPlaylistLink (playlist: Pick<VideoPlaylist, 'shortUUID'>, base?: string) {
+ return (base ?? window.location.origin) + buildPlaylistWatchPath(playlist)
+}
+
+function buildPlaylistWatchPath (playlist: Pick<VideoPlaylist, 'shortUUID'>) {
+ return '/w/p/' + playlist.shortUUID
+}
+
+function buildVideoWatchPath (video: Pick<Video, 'shortUUID'>) {
+ return '/w/' + video.shortUUID
+}
+
+function buildVideoLink (video: Pick<Video, 'shortUUID'>, base?: string) {
+ return (base ?? window.location.origin) + buildVideoWatchPath(video)
+}
+
+function buildPlaylistEmbedPath (playlist: Pick<VideoPlaylist, 'uuid'>) {
+ return '/video-playlists/embed/' + playlist.uuid
+}
+
+function buildPlaylistEmbedLink (playlist: Pick<VideoPlaylist, 'uuid'>, base?: string) {
+ return (base ?? window.location.origin) + buildPlaylistEmbedPath(playlist)
+}
+
+function buildVideoEmbedPath (video: Pick<Video, 'uuid'>) {
+ return '/videos/embed/' + video.uuid
+}
+
+function buildVideoEmbedLink (video: Pick<Video, 'uuid'>, base?: string) {
+ return (base ?? window.location.origin) + buildVideoEmbedPath(video)
+}
+
+function decorateVideoLink (options: {
+ url: string
+
+ startTime?: number
+ stopTime?: number
+
+ subtitle?: string
+
+ loop?: boolean
+ autoplay?: boolean
+ muted?: boolean
+
+ // Embed options
+ title?: boolean
+ warningTitle?: boolean
+ controls?: boolean
+ peertubeLink?: boolean
+}) {
+ const { url } = options
+
+ const params = generateParams(window.location.search)
+
+ if (options.startTime !== undefined && options.startTime !== null) {
+ const startTimeInt = Math.floor(options.startTime)
+ params.set('start', secondsToTime(startTimeInt))
+ }
+
+ if (options.stopTime) {
+ const stopTimeInt = Math.floor(options.stopTime)
+ params.set('stop', secondsToTime(stopTimeInt))
+ }
+
+ if (options.subtitle) params.set('subtitle', options.subtitle)
+
+ if (options.loop === true) params.set('loop', '1')
+ if (options.autoplay === true) params.set('autoplay', '1')
+ if (options.muted === true) params.set('muted', '1')
+ if (options.title === false) params.set('title', '0')
+ if (options.warningTitle === false) params.set('warningTitle', '0')
+ if (options.controls === false) params.set('controls', '0')
+ if (options.peertubeLink === false) params.set('peertubeLink', '0')
+
+ return buildUrl(url, params)
+}
+
+function decoratePlaylistLink (options: {
+ url: string
+
+ playlistPosition?: number
+}) {
+ const { url } = options
+
+ const params = generateParams(window.location.search)
+
+ if (options.playlistPosition) params.set('playlistPosition', '' + options.playlistPosition)
+
+ return buildUrl(url, params)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ buildPlaylistLink,
+ buildVideoLink,
+
+ buildVideoWatchPath,
+ buildPlaylistWatchPath,
+
+ buildPlaylistEmbedPath,
+ buildVideoEmbedPath,
+
+ buildPlaylistEmbedLink,
+ buildVideoEmbedLink,
+
+ decorateVideoLink,
+ decoratePlaylistLink
+}
+
+function buildUrl (url: string, params: URLSearchParams) {
+ let hasParams = false
+ params.forEach(() => { hasParams = true })
+
+ if (hasParams) return url + '?' + params.toString()
+
+ return url
+}
+
+function generateParams (url: string) {
+ const params = new URLSearchParams(window.location.search)
+ // Unused parameters in embed
+ params.delete('videoId')
+ params.delete('resume')
+
+ return params
+}
export * from './abuse'
+export * from './common'
export * from './i18n'
-export * from './logs'
-export * from './miscs'
export * from './plugins'
export * from './renderer'
export * from './users'
+export * from './utils'
+++ /dev/null
-export * from './logs'
+++ /dev/null
-import { stat } from 'fs-extra'
-
-async function mtimeSortFilesDesc (files: string[], basePath: string) {
- const promises = []
- const out: { file: string, mtime: number }[] = []
-
- for (const file of files) {
- const p = stat(basePath + '/' + file)
- .then(stats => {
- if (stats.isFile()) out.push({ file, mtime: stats.mtime.getTime() })
- })
-
- promises.push(p)
- }
-
- await Promise.all(promises)
-
- out.sort((a, b) => b.mtime - a.mtime)
-
- return out
-}
-
-export {
- mtimeSortFilesDesc
-}
+++ /dev/null
-export * from './date'
-export * from './miscs'
-export * from './types'
-export * from './http-error-codes'
-export * from './http-methods'
import { HookType } from '../../models/plugins/hook-type.enum'
-import { isCatchable, isPromise } from '../miscs/miscs'
+import { isCatchable, isPromise } from '../common/promises'
function getHookType (hookName: string) {
if (hookName.startsWith('filter:')) return HookType.FILTER
--- /dev/null
+export * from './object'
--- /dev/null
+function pick <O extends object, K extends keyof O> (object: O, keys: K[]): Pick<O, K> {
+ const result: any = {}
+
+ for (const key of keys) {
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
+ result[key] = object[key]
+ }
+ }
+
+ return result
+}
+
+export {
+ pick
+}
--- /dev/null
+import { BulkRemoveCommentsOfBody, HttpStatusCode } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class BulkCommand extends AbstractCommand {
+
+ removeCommentsOf (options: OverrideCommandOptions & {
+ attributes: BulkRemoveCommentsOfBody
+ }) {
+ const { attributes } = options
+
+ return this.postBodyRequest({
+ ...options,
+
+ path: '/api/v1/bulk/remove-comments-of',
+ fields: attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import { BulkRemoveCommentsOfBody } from "@shared/models/bulk/bulk-remove-comments-of-body.model"
-import { makePostBodyRequest } from "../requests/requests"
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function bulkRemoveCommentsOf (options: {
- url: string
- token: string
- attributes: BulkRemoveCommentsOfBody
- expectedStatus?: number
-}) {
- const { url, token, attributes, expectedStatus } = options
- const path = '/api/v1/bulk/remove-comments-of'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: attributes,
- statusCodeExpected: expectedStatus || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-export {
- bulkRemoveCommentsOf
-}
--- /dev/null
+export * from './bulk-command'
--- /dev/null
+import { exec } from 'child_process'
+import { AbstractCommand } from '../shared'
+
+export class CLICommand extends AbstractCommand {
+
+ static exec (command: string) {
+ return new Promise<string>((res, rej) => {
+ exec(command, (err, stdout, _stderr) => {
+ if (err) return rej(err)
+
+ return res(stdout)
+ })
+ })
+ }
+
+ getEnv () {
+ return `NODE_ENV=test NODE_APP_INSTANCE=${this.server.internalServerNumber}`
+ }
+
+ async execWithEnv (command: string) {
+ return CLICommand.exec(`${this.getEnv()} ${command}`)
+ }
+}
+++ /dev/null
-import { exec } from 'child_process'
-
-import { ServerInfo } from '../server/servers'
-
-function getEnvCli (server?: ServerInfo) {
- return `NODE_ENV=test NODE_APP_INSTANCE=${server.internalServerNumber}`
-}
-
-async function execCLI (command: string) {
- return new Promise<string>((res, rej) => {
- exec(command, (err, stdout, stderr) => {
- if (err) return rej(err)
-
- return res(stdout)
- })
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- execCLI,
- getEnvCli
-}
--- /dev/null
+export * from './cli-command'
--- /dev/null
+import { CustomPage, HttpStatusCode } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class CustomPagesCommand extends AbstractCommand {
+
+ getInstanceHomepage (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/custom-pages/homepage/instance'
+
+ return this.getRequestBody<CustomPage>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ updateInstanceHomepage (options: OverrideCommandOptions & {
+ content: string
+ }) {
+ const { content } = options
+ const path = '/api/v1/custom-pages/homepage/instance'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: { content },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { makeGetRequest, makePutBodyRequest } from '../requests/requests'
-
-function getInstanceHomepage (url: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/custom-pages/homepage/instance'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected
- })
-}
-
-function updateInstanceHomepage (url: string, token: string, content: string) {
- const path = '/api/v1/custom-pages/homepage/instance'
-
- return makePutBodyRequest({
- url,
- path,
- token,
- fields: { content },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getInstanceHomepage,
- updateInstanceHomepage
-}
--- /dev/null
+export * from './custom-pages-command'
--- /dev/null
+
+import { HttpStatusCode } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+type FeedType = 'videos' | 'video-comments' | 'subscriptions'
+
+export class FeedCommand extends AbstractCommand {
+
+ getXML (options: OverrideCommandOptions & {
+ feed: FeedType
+ format?: string
+ }) {
+ const { feed, format } = options
+ const path = '/feeds/' + feed + '.xml'
+
+ return this.getRequestText({
+ ...options,
+
+ path,
+ query: format ? { format } : undefined,
+ accept: 'application/xml',
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getJSON (options: OverrideCommandOptions & {
+ feed: FeedType
+ query?: { [ id: string ]: any }
+ }) {
+ const { feed, query } = options
+ const path = '/feeds/' + feed + '.json'
+
+ return this.getRequestText({
+ ...options,
+
+ path,
+ query,
+ accept: 'application/json',
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-type FeedType = 'videos' | 'video-comments' | 'subscriptions'
-
-function getXMLfeed (url: string, feed: FeedType, format?: string) {
- const path = '/feeds/' + feed + '.xml'
-
- return request(url)
- .get(path)
- .query((format) ? { format: format } : {})
- .set('Accept', 'application/xml')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /xml/)
-}
-
-function getJSONfeed (url: string, feed: FeedType, query: any = {}, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/feeds/' + feed + '.json'
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(statusCodeExpected)
- .expect('Content-Type', /json/)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getXMLfeed,
- getJSONfeed
-}
--- /dev/null
+export * from './feeds-command'
-export * from './bulk/bulk'
-
-export * from './cli/cli'
-
-export * from './custom-pages/custom-pages'
-
-export * from './feeds/feeds'
-
-export * from './mock-servers/mock-instances-index'
-
-export * from './miscs/email'
-export * from './miscs/sql'
-export * from './miscs/miscs'
-export * from './miscs/stubs'
-
-export * from './moderation/abuses'
-export * from './plugins/mock-blocklist'
-
-export * from './requests/check-api-params'
-export * from './requests/requests'
-
-export * from './search/video-channels'
-export * from './search/video-playlists'
-export * from './search/videos'
-
-export * from './server/activitypub'
-export * from './server/clients'
-export * from './server/config'
-export * from './server/debug'
-export * from './server/follows'
-export * from './server/jobs'
-export * from './server/plugins'
-export * from './server/servers'
-
-export * from './users/accounts'
-export * from './users/blocklist'
-export * from './users/login'
-export * from './users/user-notifications'
-export * from './users/user-subscriptions'
-export * from './users/users'
-
-export * from './videos/live'
-export * from './videos/services'
-export * from './videos/video-blacklist'
-export * from './videos/video-captions'
-export * from './videos/video-change-ownership'
-export * from './videos/video-channels'
-export * from './videos/video-comments'
-export * from './videos/video-playlists'
-export * from './videos/video-streaming-playlists'
-export * from './videos/videos'
+export * from './bulk'
+export * from './cli'
+export * from './custom-pages'
+export * from './feeds'
+export * from './logs'
+export * from './miscs'
+export * from './mock-servers'
+export * from './moderation'
+export * from './overviews'
+export * from './requests'
+export * from './search'
+export * from './server'
+export * from './socket'
+export * from './users'
+export * from './videos'
--- /dev/null
+export * from './logs-command'
--- /dev/null
+import { HttpStatusCode } from '@shared/models'
+import { LogLevel } from '../../models/server/log-level.type'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class LogsCommand extends AbstractCommand {
+
+ getLogs (options: OverrideCommandOptions & {
+ startDate: Date
+ endDate?: Date
+ level?: LogLevel
+ }) {
+ const { startDate, endDate, level } = options
+ const path = '/api/v1/server/logs'
+
+ return this.getRequestBody({
+ ...options,
+
+ path,
+ query: { startDate, endDate, level },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getAuditLogs (options: OverrideCommandOptions & {
+ startDate: Date
+ endDate?: Date
+ }) {
+ const { startDate, endDate } = options
+
+ const path = '/api/v1/server/audit-logs'
+
+ return this.getRequestBody({
+ ...options,
+
+ path,
+ query: { startDate, endDate },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+}
+++ /dev/null
-import { makeGetRequest } from '../requests/requests'
-import { LogLevel } from '../../models/server/log-level.type'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getLogs (url: string, accessToken: string, startDate: Date, endDate?: Date, level?: LogLevel) {
- const path = '/api/v1/server/logs'
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- query: { startDate, endDate, level },
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getAuditLogs (url: string, accessToken: string, startDate: Date, endDate?: Date) {
- const path = '/api/v1/server/audit-logs'
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- query: { startDate, endDate },
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-export {
- getLogs,
- getAuditLogs
-}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
+
+import { expect } from 'chai'
+import { pathExists, readFile } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { HttpStatusCode } from '@shared/models'
+import { makeGetRequest } from '../requests'
+import { PeerTubeServer } from '../server'
+
+// Default interval -> 5 minutes
+function dateIsValid (dateString: string, interval = 300000) {
+ const dateToCheck = new Date(dateString)
+ const now = new Date()
+
+ return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
+}
+
+async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
+ const res = await makeGetRequest({
+ url,
+ path: imagePath,
+ expectedStatus: HttpStatusCode.OK_200
+ })
+
+ const body = res.body
+
+ const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
+ const minLength = body.length - ((30 * body.length) / 100)
+ const maxLength = body.length + ((30 * body.length) / 100)
+
+ expect(data.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
+ expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
+}
+
+async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
+ const base = server.servers.buildDirectory(directory)
+
+ expect(await pathExists(join(base, filePath))).to.equal(exist)
+}
+
+export {
+ dateIsValid,
+ testImage,
+ testFileExistsOrNot
+}
--- /dev/null
+import * as ffmpeg from 'fluent-ffmpeg'
+import { ensureDir, pathExists } from 'fs-extra'
+import { dirname } from 'path'
+import { buildAbsoluteFixturePath } from './tests'
+
+async function generateHighBitrateVideo () {
+ const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
+
+ await ensureDir(dirname(tempFixturePath))
+
+ const exists = await pathExists(tempFixturePath)
+ if (!exists) {
+ console.log('Generating high bitrate video.')
+
+ // Generate a random, high bitrate video on the fly, so we don't have to include
+ // a large file in the repo. The video needs to have a certain minimum length so
+ // that FFmpeg properly applies bitrate limits.
+ // https://stackoverflow.com/a/15795112
+ return new Promise<string>((res, rej) => {
+ ffmpeg()
+ .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
+ .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
+ .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
+ .output(tempFixturePath)
+ .on('error', rej)
+ .on('end', () => res(tempFixturePath))
+ .run()
+ })
+ }
+
+ return tempFixturePath
+}
+
+async function generateVideoWithFramerate (fps = 60) {
+ const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
+
+ await ensureDir(dirname(tempFixturePath))
+
+ const exists = await pathExists(tempFixturePath)
+ if (!exists) {
+ console.log('Generating video with framerate %d.', fps)
+
+ return new Promise<string>((res, rej) => {
+ ffmpeg()
+ .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
+ .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
+ .outputOptions([ `-r ${fps}` ])
+ .output(tempFixturePath)
+ .on('error', rej)
+ .on('end', () => res(tempFixturePath))
+ .run()
+ })
+ }
+
+ return tempFixturePath
+}
+
+export {
+ generateHighBitrateVideo,
+ generateVideoWithFramerate
+}
--- /dev/null
+export * from './checks'
+export * from './generate'
+export * from './sql-command'
+export * from './tests'
+export * from './webtorrent'
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import * as chai from 'chai'
-import * as ffmpeg from 'fluent-ffmpeg'
-import { ensureDir, pathExists, readFile, stat } from 'fs-extra'
-import { basename, dirname, isAbsolute, join, resolve } from 'path'
-import * as request from 'supertest'
-import * as WebTorrent from 'webtorrent'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-const expect = chai.expect
-let webtorrent: WebTorrent.Instance
-
-function immutableAssign<T, U> (target: T, source: U) {
- return Object.assign<{}, T, U>({}, target, source)
-}
-
-// Default interval -> 5 minutes
-function dateIsValid (dateString: string, interval = 300000) {
- const dateToCheck = new Date(dateString)
- const now = new Date()
-
- return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
-}
-
-function wait (milliseconds: number) {
- return new Promise(resolve => setTimeout(resolve, milliseconds))
-}
-
-function webtorrentAdd (torrent: string, refreshWebTorrent = false) {
- const WebTorrent = require('webtorrent')
-
- if (!webtorrent) webtorrent = new WebTorrent()
- if (refreshWebTorrent === true) webtorrent = new WebTorrent()
-
- return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res))
-}
-
-function root () {
- // We are in /miscs
- let root = join(__dirname, '..', '..', '..')
-
- if (basename(root) === 'dist') root = resolve(root, '..')
-
- return root
-}
-
-function buildServerDirectory (server: { internalServerNumber: number }, directory: string) {
- return join(root(), 'test' + server.internalServerNumber, directory)
-}
-
-async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
- const res = await request(url)
- .get(imagePath)
- .expect(HttpStatusCode.OK_200)
-
- const body = res.body
-
- const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
- const minLength = body.length - ((30 * body.length) / 100)
- const maxLength = body.length + ((30 * body.length) / 100)
-
- expect(data.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
- expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
-}
-
-async function testFileExistsOrNot (server: { internalServerNumber: number }, directory: string, filePath: string, exist: boolean) {
- const base = buildServerDirectory(server, directory)
-
- expect(await pathExists(join(base, filePath))).to.equal(exist)
-}
-
-function isGithubCI () {
- return !!process.env.GITHUB_WORKSPACE
-}
-
-function buildAbsoluteFixturePath (path: string, customCIPath = false) {
- if (isAbsolute(path)) return path
-
- if (customCIPath && process.env.GITHUB_WORKSPACE) {
- return join(process.env.GITHUB_WORKSPACE, 'fixtures', path)
- }
-
- return join(root(), 'server', 'tests', 'fixtures', path)
-}
-
-function areHttpImportTestsDisabled () {
- const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true'
-
- if (disabled) console.log('Import tests are disabled')
-
- return disabled
-}
-
-async function generateHighBitrateVideo () {
- const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
-
- await ensureDir(dirname(tempFixturePath))
-
- const exists = await pathExists(tempFixturePath)
- if (!exists) {
- console.log('Generating high bitrate video.')
-
- // Generate a random, high bitrate video on the fly, so we don't have to include
- // a large file in the repo. The video needs to have a certain minimum length so
- // that FFmpeg properly applies bitrate limits.
- // https://stackoverflow.com/a/15795112
- return new Promise<string>((res, rej) => {
- ffmpeg()
- .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
- .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
- .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
- .output(tempFixturePath)
- .on('error', rej)
- .on('end', () => res(tempFixturePath))
- .run()
- })
- }
-
- return tempFixturePath
-}
-
-async function generateVideoWithFramerate (fps = 60) {
- const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
-
- await ensureDir(dirname(tempFixturePath))
-
- const exists = await pathExists(tempFixturePath)
- if (!exists) {
- console.log('Generating video with framerate %d.', fps)
-
- return new Promise<string>((res, rej) => {
- ffmpeg()
- .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
- .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
- .outputOptions([ `-r ${fps}` ])
- .output(tempFixturePath)
- .on('error', rej)
- .on('end', () => res(tempFixturePath))
- .run()
- })
- }
-
- return tempFixturePath
-}
-
-async function getFileSize (path: string) {
- const stats = await stat(path)
-
- return stats.size
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- dateIsValid,
- wait,
- areHttpImportTestsDisabled,
- buildServerDirectory,
- webtorrentAdd,
- getFileSize,
- immutableAssign,
- testImage,
- isGithubCI,
- buildAbsoluteFixturePath,
- testFileExistsOrNot,
- root,
- generateHighBitrateVideo,
- generateVideoWithFramerate
-}
--- /dev/null
+import { QueryTypes, Sequelize } from 'sequelize'
+import { AbstractCommand } from '../shared/abstract-command'
+
+export class SQLCommand extends AbstractCommand {
+ private sequelize: Sequelize
+
+ deleteAll (table: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.DELETE }
+
+ return seq.query(`DELETE FROM "${table}"`, options)
+ }
+
+ async getCount (table: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
+
+ const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options)
+ if (total === null) return 0
+
+ return parseInt(total, 10)
+ }
+
+ setActorField (to: string, field: string, value: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options)
+ }
+
+ setVideoField (uuid: string, field: string, value: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
+ }
+
+ setPlaylistField (uuid: string, field: string, value: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
+ }
+
+ async countVideoViewsOf (uuid: string) {
+ const seq = this.getSequelize()
+
+ // tslint:disable
+ const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
+ `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'`
+
+ const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
+ const [ { total } ] = await seq.query<{ total: number }>(query, options)
+
+ if (!total) return 0
+
+ return parseInt(total + '', 10)
+ }
+
+ getActorImage (filename: string) {
+ return this.selectQuery(`SELECT * FROM "actorImage" WHERE filename = '${filename}'`)
+ .then(rows => rows[0])
+ }
+
+ selectQuery (query: string) {
+ const seq = this.getSequelize()
+ const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
+
+ return seq.query<any>(query, options)
+ }
+
+ updateQuery (query: string) {
+ const seq = this.getSequelize()
+ const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE }
+
+ return seq.query(query, options)
+ }
+
+ setPluginField (pluginName: string, field: string, value: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options)
+ }
+
+ setPluginVersion (pluginName: string, newVersion: string) {
+ return this.setPluginField(pluginName, 'version', newVersion)
+ }
+
+ setPluginLatestVersion (pluginName: string, newVersion: string) {
+ return this.setPluginField(pluginName, 'latestVersion', newVersion)
+ }
+
+ setActorFollowScores (newScore: number) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options)
+ }
+
+ setTokenField (accessToken: string, field: string, value: string) {
+ const seq = this.getSequelize()
+
+ const options = { type: QueryTypes.UPDATE }
+
+ return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options)
+ }
+
+ async cleanup () {
+ if (!this.sequelize) return
+
+ await this.sequelize.close()
+ this.sequelize = undefined
+ }
+
+ private getSequelize () {
+ if (this.sequelize) return this.sequelize
+
+ const dbname = 'peertube_test' + this.server.internalServerNumber
+ const username = 'peertube'
+ const password = 'peertube'
+ const host = 'localhost'
+ const port = 5432
+
+ this.sequelize = new Sequelize(dbname, username, password, {
+ dialect: 'postgres',
+ host,
+ port,
+ logging: false
+ })
+
+ return this.sequelize
+ }
+
+}
+++ /dev/null
-import { QueryTypes, Sequelize } from 'sequelize'
-import { ServerInfo } from '../server/servers'
-
-const sequelizes: { [ id: number ]: Sequelize } = {}
-
-function getSequelize (internalServerNumber: number) {
- if (sequelizes[internalServerNumber]) return sequelizes[internalServerNumber]
-
- const dbname = 'peertube_test' + internalServerNumber
- const username = 'peertube'
- const password = 'peertube'
- const host = 'localhost'
- const port = 5432
-
- const seq = new Sequelize(dbname, username, password, {
- dialect: 'postgres',
- host,
- port,
- logging: false
- })
-
- sequelizes[internalServerNumber] = seq
-
- return seq
-}
-
-function deleteAll (internalServerNumber: number, table: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.DELETE }
-
- return seq.query(`DELETE FROM "${table}"`, options)
-}
-
-async function getCount (internalServerNumber: number, table: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
-
- const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options)
- if (total === null) return 0
-
- return parseInt(total, 10)
-}
-
-function setActorField (internalServerNumber: number, to: string, field: string, value: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options)
-}
-
-function setVideoField (internalServerNumber: number, uuid: string, field: string, value: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
-}
-
-function setPlaylistField (internalServerNumber: number, uuid: string, field: string, value: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
-}
-
-async function countVideoViewsOf (internalServerNumber: number, uuid: string) {
- const seq = getSequelize(internalServerNumber)
-
- // tslint:disable
- const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
- `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'`
-
- const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
- const [ { total } ] = await seq.query<{ total: number }>(query, options)
-
- if (!total) return 0
-
- return parseInt(total + '', 10)
-}
-
-function getActorImage (internalServerNumber: number, filename: string) {
- return selectQuery(internalServerNumber, `SELECT * FROM "actorImage" WHERE filename = '${filename}'`)
- .then(rows => rows[0])
-}
-
-function selectQuery (internalServerNumber: number, query: string) {
- const seq = getSequelize(internalServerNumber)
- const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
-
- return seq.query<any>(query, options)
-}
-
-function updateQuery (internalServerNumber: number, query: string) {
- const seq = getSequelize(internalServerNumber)
- const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE }
-
- return seq.query(query, options)
-}
-
-async function closeAllSequelize (servers: ServerInfo[]) {
- for (const server of servers) {
- if (sequelizes[server.internalServerNumber]) {
- await sequelizes[server.internalServerNumber].close()
- // eslint-disable-next-line
- delete sequelizes[server.internalServerNumber]
- }
- }
-}
-
-function setPluginField (internalServerNumber: number, pluginName: string, field: string, value: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options)
-}
-
-function setPluginVersion (internalServerNumber: number, pluginName: string, newVersion: string) {
- return setPluginField(internalServerNumber, pluginName, 'version', newVersion)
-}
-
-function setPluginLatestVersion (internalServerNumber: number, pluginName: string, newVersion: string) {
- return setPluginField(internalServerNumber, pluginName, 'latestVersion', newVersion)
-}
-
-function setActorFollowScores (internalServerNumber: number, newScore: number) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options)
-}
-
-function setTokenField (internalServerNumber: number, accessToken: string, field: string, value: string) {
- const seq = getSequelize(internalServerNumber)
-
- const options = { type: QueryTypes.UPDATE }
-
- return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options)
-}
-
-export {
- setVideoField,
- setPlaylistField,
- setActorField,
- countVideoViewsOf,
- setPluginVersion,
- setPluginLatestVersion,
- selectQuery,
- getActorImage,
- deleteAll,
- setTokenField,
- updateQuery,
- setActorFollowScores,
- closeAllSequelize,
- getCount
-}
+++ /dev/null
-function buildRequestStub (): any {
- return { }
-}
-
-function buildResponseStub (): any {
- return {
- locals: {}
- }
-}
-
-export {
- buildResponseStub,
- buildRequestStub
-}
--- /dev/null
+import { stat } from 'fs-extra'
+import { basename, isAbsolute, join, resolve } from 'path'
+
+const FIXTURE_URLS = {
+ youtube: 'https://www.youtube.com/watch?v=msX3jv1XdvM',
+
+ /**
+ * The video is used to check format-selection correctness wrt. HDR,
+ * which brings its own set of oddities outside of a MediaSource.
+ * FIXME: refactor once HDR is supported at playback
+ *
+ * The video needs to have the following format_ids:
+ * (which you can check by using `youtube-dl <url> -F`):
+ * - 303 (1080p webm vp9)
+ * - 299 (1080p mp4 avc1)
+ * - 335 (1080p webm vp9.2 HDR)
+ *
+ * 15 jan. 2021: TEST VIDEO NOT CURRENTLY PROVIDING
+ * - 400 (1080p mp4 av01)
+ * - 315 (2160p webm vp9 HDR)
+ * - 337 (2160p webm vp9.2 HDR)
+ * - 401 (2160p mp4 av01 HDR)
+ */
+ youtubeHDR: 'https://www.youtube.com/watch?v=qR5vOXbZsI4',
+
+ // eslint-disable-next-line max-len
+ magnet: 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4',
+
+ badVideo: 'https://download.cpy.re/peertube/bad_video.mp4',
+ goodVideo: 'https://download.cpy.re/peertube/good_video.mp4',
+ video4K: 'https://download.cpy.re/peertube/4k_file.txt'
+}
+
+function parallelTests () {
+ return process.env.MOCHA_PARALLEL === 'true'
+}
+
+function isGithubCI () {
+ return !!process.env.GITHUB_WORKSPACE
+}
+
+function areHttpImportTestsDisabled () {
+ const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true'
+
+ if (disabled) console.log('Import tests are disabled')
+
+ return disabled
+}
+
+function buildAbsoluteFixturePath (path: string, customCIPath = false) {
+ if (isAbsolute(path)) return path
+
+ if (customCIPath && process.env.GITHUB_WORKSPACE) {
+ return join(process.env.GITHUB_WORKSPACE, 'fixtures', path)
+ }
+
+ return join(root(), 'server', 'tests', 'fixtures', path)
+}
+
+function root () {
+ // We are in /miscs
+ let root = join(__dirname, '..', '..', '..')
+
+ if (basename(root) === 'dist') root = resolve(root, '..')
+
+ return root
+}
+
+function wait (milliseconds: number) {
+ return new Promise(resolve => setTimeout(resolve, milliseconds))
+}
+
+async function getFileSize (path: string) {
+ const stats = await stat(path)
+
+ return stats.size
+}
+
+function buildRequestStub (): any {
+ return { }
+}
+
+export {
+ FIXTURE_URLS,
+
+ parallelTests,
+ isGithubCI,
+ areHttpImportTestsDisabled,
+ buildAbsoluteFixturePath,
+ getFileSize,
+ buildRequestStub,
+ wait,
+ root
+}
--- /dev/null
+import { readFile } from 'fs-extra'
+import * as parseTorrent from 'parse-torrent'
+import { basename, join } from 'path'
+import * as WebTorrent from 'webtorrent'
+import { VideoFile } from '@shared/models'
+import { PeerTubeServer } from '../server'
+
+let webtorrent: WebTorrent.Instance
+
+function webtorrentAdd (torrent: string, refreshWebTorrent = false) {
+ const WebTorrent = require('webtorrent')
+
+ if (!webtorrent) webtorrent = new WebTorrent()
+ if (refreshWebTorrent === true) webtorrent = new WebTorrent()
+
+ return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res))
+}
+
+async function parseTorrentVideo (server: PeerTubeServer, file: VideoFile) {
+ const torrentName = basename(file.torrentUrl)
+ const torrentPath = server.servers.buildDirectory(join('torrents', torrentName))
+
+ const data = await readFile(torrentPath)
+
+ return parseTorrent(data)
+}
+
+export {
+ webtorrentAdd,
+ parseTorrentVideo
+}
--- /dev/null
+export * from './mock-email'
+export * from './mock-instances-index'
+export * from './mock-joinpeertube-versions'
+export * from './mock-plugin-blocklist'
import { ChildProcess } from 'child_process'
-import { randomInt } from '../../core-utils/miscs/miscs'
-import { parallelTests } from '../server/servers'
+import { randomInt } from '@shared/core-utils'
+import { parallelTests } from '../miscs'
const MailDev = require('maildev')
--- /dev/null
+import { pick } from '@shared/core-utils'
+import {
+ AbuseFilter,
+ AbuseMessage,
+ AbusePredefinedReasonsString,
+ AbuseState,
+ AbuseUpdate,
+ AbuseVideoIs,
+ AdminAbuse,
+ HttpStatusCode,
+ ResultList,
+ UserAbuse
+} from '@shared/models'
+import { unwrapBody } from '../requests/requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class AbusesCommand extends AbstractCommand {
+
+ report (options: OverrideCommandOptions & {
+ reason: string
+
+ accountId?: number
+ videoId?: number
+ commentId?: number
+
+ predefinedReasons?: AbusePredefinedReasonsString[]
+
+ startAt?: number
+ endAt?: number
+ }) {
+ const path = '/api/v1/abuses'
+
+ const video = options.videoId
+ ? {
+ id: options.videoId,
+ startAt: options.startAt,
+ endAt: options.endAt
+ }
+ : undefined
+
+ const comment = options.commentId
+ ? { id: options.commentId }
+ : undefined
+
+ const account = options.accountId
+ ? { id: options.accountId }
+ : undefined
+
+ const body = {
+ account,
+ video,
+ comment,
+
+ reason: options.reason,
+ predefinedReasons: options.predefinedReasons
+ }
+
+ return unwrapBody<{ abuse: { id: number } }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: body,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ getAdminList (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+
+ id?: number
+ predefinedReason?: AbusePredefinedReasonsString
+ search?: string
+ filter?: AbuseFilter
+ state?: AbuseState
+ videoIs?: AbuseVideoIs
+ searchReporter?: string
+ searchReportee?: string
+ searchVideo?: string
+ searchVideoChannel?: string
+ } = {}) {
+ const toPick: (keyof typeof options)[] = [
+ 'count',
+ 'filter',
+ 'id',
+ 'predefinedReason',
+ 'search',
+ 'searchReportee',
+ 'searchReporter',
+ 'searchVideo',
+ 'searchVideoChannel',
+ 'sort',
+ 'start',
+ 'state',
+ 'videoIs'
+ ]
+
+ const path = '/api/v1/abuses'
+
+ const defaultQuery = { sort: 'createdAt' }
+ const query = { ...defaultQuery, ...pick(options, toPick) }
+
+ return this.getRequestBody<ResultList<AdminAbuse>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getUserList (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+
+ id?: number
+ search?: string
+ state?: AbuseState
+ }) {
+ const toPick: (keyof typeof options)[] = [
+ 'id',
+ 'search',
+ 'state',
+ 'start',
+ 'count',
+ 'sort'
+ ]
+
+ const path = '/api/v1/users/me/abuses'
+
+ const defaultQuery = { sort: 'createdAt' }
+ const query = { ...defaultQuery, ...pick(options, toPick) }
+
+ return this.getRequestBody<ResultList<UserAbuse>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ update (options: OverrideCommandOptions & {
+ abuseId: number
+ body: AbuseUpdate
+ }) {
+ const { abuseId, body } = options
+ const path = '/api/v1/abuses/' + abuseId
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: body,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ delete (options: OverrideCommandOptions & {
+ abuseId: number
+ }) {
+ const { abuseId } = options
+ const path = '/api/v1/abuses/' + abuseId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ listMessages (options: OverrideCommandOptions & {
+ abuseId: number
+ }) {
+ const { abuseId } = options
+ const path = '/api/v1/abuses/' + abuseId + '/messages'
+
+ return this.getRequestBody<ResultList<AbuseMessage>>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ deleteMessage (options: OverrideCommandOptions & {
+ abuseId: number
+ messageId: number
+ }) {
+ const { abuseId, messageId } = options
+ const path = '/api/v1/abuses/' + abuseId + '/messages/' + messageId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ addMessage (options: OverrideCommandOptions & {
+ abuseId: number
+ message: string
+ }) {
+ const { abuseId, message } = options
+ const path = '/api/v1/abuses/' + abuseId + '/messages'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { message },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+}
+++ /dev/null
-import { AbuseFilter, AbusePredefinedReasonsString, AbuseState, AbuseUpdate, AbuseVideoIs } from '@shared/models'
-import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function reportAbuse (options: {
- url: string
- token: string
-
- reason: string
-
- accountId?: number
- videoId?: number
- commentId?: number
-
- predefinedReasons?: AbusePredefinedReasonsString[]
-
- startAt?: number
- endAt?: number
-
- statusCodeExpected?: number
-}) {
- const path = '/api/v1/abuses'
-
- const video = options.videoId
- ? {
- id: options.videoId,
- startAt: options.startAt,
- endAt: options.endAt
- }
- : undefined
-
- const comment = options.commentId
- ? { id: options.commentId }
- : undefined
-
- const account = options.accountId
- ? { id: options.accountId }
- : undefined
-
- const body = {
- account,
- video,
- comment,
-
- reason: options.reason,
- predefinedReasons: options.predefinedReasons
- }
-
- return makePostBodyRequest({
- url: options.url,
- path,
- token: options.token,
-
- fields: body,
- statusCodeExpected: options.statusCodeExpected || HttpStatusCode.OK_200
- })
-}
-
-function getAdminAbusesList (options: {
- url: string
- token: string
-
- start?: number
- count?: number
- sort?: string
-
- id?: number
- predefinedReason?: AbusePredefinedReasonsString
- search?: string
- filter?: AbuseFilter
- state?: AbuseState
- videoIs?: AbuseVideoIs
- searchReporter?: string
- searchReportee?: string
- searchVideo?: string
- searchVideoChannel?: string
-}) {
- const {
- url,
- token,
- start,
- count,
- sort,
- id,
- predefinedReason,
- search,
- filter,
- state,
- videoIs,
- searchReporter,
- searchReportee,
- searchVideo,
- searchVideoChannel
- } = options
- const path = '/api/v1/abuses'
-
- const query = {
- id,
- predefinedReason,
- search,
- state,
- filter,
- videoIs,
- start,
- count,
- sort: sort || 'createdAt',
- searchReporter,
- searchReportee,
- searchVideo,
- searchVideoChannel
- }
-
- return makeGetRequest({
- url,
- path,
- token,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getUserAbusesList (options: {
- url: string
- token: string
-
- start?: number
- count?: number
- sort?: string
-
- id?: number
- search?: string
- state?: AbuseState
-}) {
- const {
- url,
- token,
- start,
- count,
- sort,
- id,
- search,
- state
- } = options
- const path = '/api/v1/users/me/abuses'
-
- const query = {
- id,
- search,
- state,
- start,
- count,
- sort: sort || 'createdAt'
- }
-
- return makeGetRequest({
- url,
- path,
- token,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function updateAbuse (
- url: string,
- token: string,
- abuseId: number,
- body: AbuseUpdate,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/abuses/' + abuseId
-
- return makePutBodyRequest({
- url,
- token,
- path,
- fields: body,
- statusCodeExpected
- })
-}
-
-function deleteAbuse (url: string, token: string, abuseId: number, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/abuses/' + abuseId
-
- return makeDeleteRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function listAbuseMessages (url: string, token: string, abuseId: number, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/abuses/' + abuseId + '/messages'
-
- return makeGetRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function deleteAbuseMessage (
- url: string,
- token: string,
- abuseId: number,
- messageId: number,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/abuses/' + abuseId + '/messages/' + messageId
-
- return makeDeleteRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function addAbuseMessage (url: string, token: string, abuseId: number, message: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/abuses/' + abuseId + '/messages'
-
- return makePostBodyRequest({
- url,
- token,
- path,
- fields: { message },
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- reportAbuse,
- getAdminAbusesList,
- updateAbuse,
- deleteAbuse,
- getUserAbusesList,
- listAbuseMessages,
- deleteAbuseMessage,
- addAbuseMessage
-}
--- /dev/null
+export * from './abuses-command'
--- /dev/null
+export * from './overviews-command'
--- /dev/null
+import { HttpStatusCode, VideosOverview } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class OverviewsCommand extends AbstractCommand {
+
+ getVideos (options: OverrideCommandOptions & {
+ page: number
+ }) {
+ const { page } = options
+ const path = '/api/v1/overviews/videos'
+
+ const query = { page }
+
+ return this.getRequestBody<VideosOverview>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import { makeGetRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getVideosOverview (url: string, page: number, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/overviews/videos'
-
- const query = { page }
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected
- })
-}
-
-function getVideosOverviewWithToken (url: string, page: number, token: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/overviews/videos'
-
- const query = { page }
-
- return makeGetRequest({
- url,
- path,
- query,
- token,
- statusCodeExpected
- })
-}
-
-export {
- getVideosOverview,
- getVideosOverviewWithToken
-}
+import { activityPubContextify } from '../../../server/helpers/activitypub'
import { doRequest } from '../../../server/helpers/requests'
import { HTTP_SIGNATURE } from '../../../server/initializers/constants'
import { buildGlobalHeaders } from '../../../server/lib/job-queue/handlers/utils/activitypub-http-utils'
-import { activityPubContextify } from '../../../server/helpers/activitypub'
function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) {
const options = {
+import { HttpStatusCode } from '@shared/models'
import { makeGetRequest } from './requests'
-import { immutableAssign } from '../miscs/miscs'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
function checkBadStartPagination (url: string, path: string, token?: string, query = {}) {
return makeGetRequest({
url,
path,
token,
- query: immutableAssign(query, { start: 'hello' }),
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ query: { ...query, start: 'hello' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
url,
path,
token,
- query: immutableAssign(query, { count: 'hello' }),
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ query: { ...query, count: 'hello' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
await makeGetRequest({
url,
path,
token,
- query: immutableAssign(query, { count: 2000 }),
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ query: { ...query, count: 2000 },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
url,
path,
token,
- query: immutableAssign(query, { sort: 'hello' }),
- statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
+ query: { ...query, sort: 'hello' },
+ expectedStatus: HttpStatusCode.BAD_REQUEST_400
})
}
--- /dev/null
+// Don't include activitypub that import stuff from server
+export * from './check-api-params'
+export * from './requests'
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
+/* eslint-disable @typescript-eslint/no-floating-promises */
+import { decode } from 'querystring'
import * as request from 'supertest'
-import { buildAbsoluteFixturePath, root } from '../miscs/miscs'
-import { isAbsolute, join } from 'path'
import { URL } from 'url'
-import { decode } from 'querystring'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { HttpStatusCode } from '@shared/models'
+import { buildAbsoluteFixturePath } from '../miscs/tests'
-function get4KFileUrl () {
- return 'https://download.cpy.re/peertube/4k_file.txt'
+export type CommonRequestParams = {
+ url: string
+ path?: string
+ contentType?: string
+ range?: string
+ redirects?: number
+ accept?: string
+ host?: string
+ token?: string
+ headers?: { [ name: string ]: string }
+ type?: string
+ xForwardedFor?: string
+ expectedStatus?: HttpStatusCode
}
-function makeRawRequest (url: string, statusCodeExpected?: HttpStatusCode, range?: string) {
+function makeRawRequest (url: string, expectedStatus?: HttpStatusCode, range?: string) {
const { host, protocol, pathname } = new URL(url)
- return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, statusCodeExpected, range })
+ return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, expectedStatus, range })
}
-function makeGetRequest (options: {
- url: string
- path?: string
+function makeGetRequest (options: CommonRequestParams & {
query?: any
- token?: string
- statusCodeExpected?: HttpStatusCode
- contentType?: string
- range?: string
- redirects?: number
- accept?: string
}) {
- if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
- if (options.contentType === undefined) options.contentType = 'application/json'
-
const req = request(options.url).get(options.path)
+ .query(options.query)
- if (options.contentType) req.set('Accept', options.contentType)
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
- if (options.query) req.query(options.query)
- if (options.range) req.set('Range', options.range)
- if (options.accept) req.set('Accept', options.accept)
- if (options.redirects) req.redirects(options.redirects)
-
- return req.expect(options.statusCodeExpected)
+ return buildRequest(req, { contentType: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
}
-function makeDeleteRequest (options: {
- url: string
- path: string
- token?: string
- statusCodeExpected?: HttpStatusCode
-}) {
- if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
+function makeHTMLRequest (url: string, path: string) {
+ return makeGetRequest({
+ url,
+ path,
+ accept: 'text/html',
+ expectedStatus: HttpStatusCode.OK_200
+ })
+}
- const req = request(options.url)
- .delete(options.path)
- .set('Accept', 'application/json')
+function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
+ return makeGetRequest({
+ url,
+ path,
+ expectedStatus: expectedStatus,
+ accept: 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8'
+ })
+}
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
+function makeDeleteRequest (options: CommonRequestParams) {
+ const req = request(options.url).delete(options.path)
- return req.expect(options.statusCodeExpected)
+ return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
}
-function makeUploadRequest (options: {
- url: string
+function makeUploadRequest (options: CommonRequestParams & {
method?: 'POST' | 'PUT'
- path: string
- token?: string
+
fields: { [ fieldName: string ]: any }
attaches?: { [ attachName: string ]: any | any[] }
- statusCodeExpected?: HttpStatusCode
}) {
- if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
-
- let req: request.Test
- if (options.method === 'PUT') {
- req = request(options.url).put(options.path)
- } else {
- req = request(options.url).post(options.path)
- }
-
- req.set('Accept', 'application/json')
+ let req = options.method === 'PUT'
+ ? request(options.url).put(options.path)
+ : request(options.url).post(options.path)
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
+ req = buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- Object.keys(options.fields).forEach(field => {
- const value = options.fields[field]
-
- if (value === undefined) return
-
- if (Array.isArray(value)) {
- for (let i = 0; i < value.length; i++) {
- req.field(field + '[' + i + ']', value[i])
- }
- } else {
- req.field(field, value)
- }
- })
+ buildFields(req, options.fields)
Object.keys(options.attaches || {}).forEach(attach => {
const value = options.attaches[attach]
+
if (Array.isArray(value)) {
req.attach(attach, buildAbsoluteFixturePath(value[0]), value[1])
} else {
}
})
- return req.expect(options.statusCodeExpected)
+ return req
}
-function makePostBodyRequest (options: {
- url: string
- path: string
- token?: string
+function makePostBodyRequest (options: CommonRequestParams & {
fields?: { [ fieldName: string ]: any }
- statusCodeExpected?: HttpStatusCode
}) {
- if (!options.fields) options.fields = {}
- if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
-
- const req = request(options.url)
- .post(options.path)
- .set('Accept', 'application/json')
+ const req = request(options.url).post(options.path)
+ .send(options.fields)
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
-
- return req.send(options.fields)
- .expect(options.statusCodeExpected)
+ return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
}
function makePutBodyRequest (options: {
path: string
token?: string
fields: { [ fieldName: string ]: any }
- statusCodeExpected?: HttpStatusCode
+ expectedStatus?: HttpStatusCode
}) {
- if (!options.statusCodeExpected) options.statusCodeExpected = HttpStatusCode.BAD_REQUEST_400
-
- const req = request(options.url)
- .put(options.path)
- .set('Accept', 'application/json')
+ const req = request(options.url).put(options.path)
+ .send(options.fields)
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
-
- return req.send(options.fields)
- .expect(options.statusCodeExpected)
+ return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
}
-function makeHTMLRequest (url: string, path: string) {
- return request(url)
- .get(path)
- .set('Accept', 'text/html')
- .expect(HttpStatusCode.OK_200)
+function decodeQueryString (path: string) {
+ return decode(path.split('?')[1])
}
-function updateImageRequest (options: {
- url: string
- path: string
- accessToken: string
- fixture: string
- fieldname: string
-}) {
- let filePath = ''
- if (isAbsolute(options.fixture)) {
- filePath = options.fixture
- } else {
- filePath = join(root(), 'server', 'tests', 'fixtures', options.fixture)
- }
-
- return makeUploadRequest({
- url: options.url,
- path: options.path,
- token: options.accessToken,
- fields: {},
- attaches: { [options.fieldname]: filePath },
- statusCodeExpected: HttpStatusCode.OK_200
- })
+function unwrapBody <T> (test: request.Test): Promise<T> {
+ return test.then(res => res.body)
}
-function decodeQueryString (path: string) {
- return decode(path.split('?')[1])
+function unwrapText (test: request.Test): Promise<string> {
+ return test.then(res => res.text)
}
// ---------------------------------------------------------------------------
export {
- get4KFileUrl,
makeHTMLRequest,
makeGetRequest,
decodeQueryString,
makePutBodyRequest,
makeDeleteRequest,
makeRawRequest,
- updateImageRequest
+ makeActivityPubGetRequest,
+ unwrapBody,
+ unwrapText
+}
+
+// ---------------------------------------------------------------------------
+
+function buildRequest (req: request.Test, options: CommonRequestParams) {
+ if (options.contentType) req.set('Accept', options.contentType)
+ if (options.token) req.set('Authorization', 'Bearer ' + options.token)
+ if (options.range) req.set('Range', options.range)
+ if (options.accept) req.set('Accept', options.accept)
+ if (options.host) req.set('Host', options.host)
+ if (options.redirects) req.redirects(options.redirects)
+ if (options.expectedStatus) req.expect(options.expectedStatus)
+ if (options.xForwardedFor) req.set('X-Forwarded-For', options.xForwardedFor)
+ if (options.type) req.type(options.type)
+
+ Object.keys(options.headers || {}).forEach(name => {
+ req.set(name, options.headers[name])
+ })
+
+ return req
+}
+
+function buildFields (req: request.Test, fields: { [ fieldName: string ]: any }, namespace?: string) {
+ if (!fields) return
+
+ let formKey: string
+
+ for (const key of Object.keys(fields)) {
+ if (namespace) formKey = `${namespace}[${key}]`
+ else formKey = key
+
+ if (fields[key] === undefined) continue
+
+ if (Array.isArray(fields[key]) && fields[key].length === 0) {
+ req.field(key, null)
+ continue
+ }
+
+ if (fields[key] !== null && typeof fields[key] === 'object') {
+ buildFields(req, fields[key], formKey)
+ } else {
+ req.field(formKey, fields[key])
+ }
+ }
}
--- /dev/null
+export * from './search-command'
--- /dev/null
+import {
+ HttpStatusCode,
+ ResultList,
+ Video,
+ VideoChannel,
+ VideoChannelsSearchQuery,
+ VideoPlaylist,
+ VideoPlaylistsSearchQuery,
+ VideosSearchQuery
+} from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class SearchCommand extends AbstractCommand {
+
+ searchChannels (options: OverrideCommandOptions & {
+ search: string
+ }) {
+ return this.advancedChannelSearch({
+ ...options,
+
+ search: { search: options.search }
+ })
+ }
+
+ advancedChannelSearch (options: OverrideCommandOptions & {
+ search: VideoChannelsSearchQuery
+ }) {
+ const { search } = options
+ const path = '/api/v1/search/video-channels'
+
+ return this.getRequestBody<ResultList<VideoChannel>>({
+ ...options,
+
+ path,
+ query: search,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ searchPlaylists (options: OverrideCommandOptions & {
+ search: string
+ }) {
+ return this.advancedPlaylistSearch({
+ ...options,
+
+ search: { search: options.search }
+ })
+ }
+
+ advancedPlaylistSearch (options: OverrideCommandOptions & {
+ search: VideoPlaylistsSearchQuery
+ }) {
+ const { search } = options
+ const path = '/api/v1/search/video-playlists'
+
+ return this.getRequestBody<ResultList<VideoPlaylist>>({
+ ...options,
+
+ path,
+ query: search,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ searchVideos (options: OverrideCommandOptions & {
+ search: string
+ sort?: string
+ }) {
+ const { search, sort } = options
+
+ return this.advancedVideoSearch({
+ ...options,
+
+ search: {
+ search: search,
+ sort: sort ?? '-publishedAt'
+ }
+ })
+ }
+
+ advancedVideoSearch (options: OverrideCommandOptions & {
+ search: VideosSearchQuery
+ }) {
+ const { search } = options
+ const path = '/api/v1/search/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: search,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import { VideoChannelsSearchQuery } from '@shared/models'
-import { makeGetRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function searchVideoChannel (url: string, search: string, token?: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/search/video-channels'
-
- return makeGetRequest({
- url,
- path,
- query: {
- sort: '-createdAt',
- search
- },
- token,
- statusCodeExpected
- })
-}
-
-function advancedVideoChannelSearch (url: string, search: VideoChannelsSearchQuery) {
- const path = '/api/v1/search/video-channels'
-
- return makeGetRequest({
- url,
- path,
- query: search,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- searchVideoChannel,
- advancedVideoChannelSearch
-}
+++ /dev/null
-import { VideoPlaylistsSearchQuery } from '@shared/models'
-import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
-import { makeGetRequest } from '../requests/requests'
-
-function searchVideoPlaylists (url: string, search: string, token?: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/search/video-playlists'
-
- return makeGetRequest({
- url,
- path,
- query: {
- sort: '-createdAt',
- search
- },
- token,
- statusCodeExpected
- })
-}
-
-function advancedVideoPlaylistSearch (url: string, search: VideoPlaylistsSearchQuery) {
- const path = '/api/v1/search/video-playlists'
-
- return makeGetRequest({
- url,
- path,
- query: search,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- searchVideoPlaylists,
- advancedVideoPlaylistSearch
-}
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import * as request from 'supertest'
-import { VideosSearchQuery } from '../../models/search'
-import { immutableAssign } from '../miscs/miscs'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function searchVideo (url: string, search: string, sort = '-publishedAt') {
- const path = '/api/v1/search/videos'
-
- const query = { sort, search: search }
- const req = request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
-
- return req.expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function searchVideoWithToken (url: string, search: string, token: string, query: { nsfw?: boolean } = {}) {
- const path = '/api/v1/search/videos'
- const req = request(url)
- .get(path)
- .set('Authorization', 'Bearer ' + token)
- .query(immutableAssign(query, { sort: '-publishedAt', search }))
- .set('Accept', 'application/json')
-
- return req.expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function searchVideoWithSort (url: string, search: string, sort: string) {
- const path = '/api/v1/search/videos'
-
- const query = { search, sort }
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function advancedVideosSearch (url: string, options: VideosSearchQuery) {
- const path = '/api/v1/search/videos'
-
- return request(url)
- .get(path)
- .query(options)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- searchVideo,
- advancedVideosSearch,
- searchVideoWithToken,
- searchVideoWithSort
-}
+++ /dev/null
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
- return request(url)
- .get(path)
- .set('Accept', 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8')
- .expect(expectedStatus)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- makeActivityPubGetRequest
-}
+++ /dev/null
-import * as request from 'supertest'
-import { URL } from 'url'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getClient (url: string) {
- const path = '/api/v1/oauth-clients/local'
-
- return request(url)
- .get(path)
- .set('Host', new URL(url).host)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getClient
-}
--- /dev/null
+import { merge } from 'lodash'
+import { DeepPartial } from '@shared/core-utils'
+import { About, HttpStatusCode, ServerConfig } from '@shared/models'
+import { CustomConfig } from '../../models/server/custom-config.model'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ConfigCommand extends AbstractCommand {
+
+ static getCustomConfigResolutions (enabled: boolean) {
+ return {
+ '240p': enabled,
+ '360p': enabled,
+ '480p': enabled,
+ '720p': enabled,
+ '1080p': enabled,
+ '1440p': enabled,
+ '2160p': enabled
+ }
+ }
+
+ getConfig (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/config'
+
+ return this.getRequestBody<ServerConfig>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getAbout (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/config/about'
+
+ return this.getRequestBody<About>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getCustomConfig (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/config/custom'
+
+ return this.getRequestBody<CustomConfig>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ updateCustomConfig (options: OverrideCommandOptions & {
+ newCustomConfig: CustomConfig
+ }) {
+ const path = '/api/v1/config/custom'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: options.newCustomConfig,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ deleteCustomConfig (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/config/custom'
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ updateCustomSubConfig (options: OverrideCommandOptions & {
+ newConfig: DeepPartial<CustomConfig>
+ }) {
+ const newCustomConfig: CustomConfig = {
+ instance: {
+ name: 'PeerTube updated',
+ shortDescription: 'my short description',
+ description: 'my super description',
+ terms: 'my super terms',
+ codeOfConduct: 'my super coc',
+
+ creationReason: 'my super creation reason',
+ moderationInformation: 'my super moderation information',
+ administrator: 'Kuja',
+ maintenanceLifetime: 'forever',
+ businessModel: 'my super business model',
+ hardwareInformation: '2vCore 3GB RAM',
+
+ languages: [ 'en', 'es' ],
+ categories: [ 1, 2 ],
+
+ isNSFW: true,
+ defaultNSFWPolicy: 'blur',
+
+ defaultClientRoute: '/videos/recently-added',
+
+ customizations: {
+ javascript: 'alert("coucou")',
+ css: 'body { background-color: red; }'
+ }
+ },
+ theme: {
+ default: 'default'
+ },
+ services: {
+ twitter: {
+ username: '@MySuperUsername',
+ whitelisted: true
+ }
+ },
+ cache: {
+ previews: {
+ size: 2
+ },
+ captions: {
+ size: 3
+ },
+ torrents: {
+ size: 4
+ }
+ },
+ signup: {
+ enabled: false,
+ limit: 5,
+ requiresEmailVerification: false,
+ minimumAge: 16
+ },
+ admin: {
+ email: 'superadmin1@example.com'
+ },
+ contactForm: {
+ enabled: true
+ },
+ user: {
+ videoQuota: 5242881,
+ videoQuotaDaily: 318742
+ },
+ transcoding: {
+ enabled: true,
+ allowAdditionalExtensions: true,
+ allowAudioFiles: true,
+ threads: 1,
+ concurrency: 3,
+ profile: 'default',
+ resolutions: {
+ '0p': false,
+ '240p': false,
+ '360p': true,
+ '480p': true,
+ '720p': false,
+ '1080p': false,
+ '1440p': false,
+ '2160p': false
+ },
+ webtorrent: {
+ enabled: true
+ },
+ hls: {
+ enabled: false
+ }
+ },
+ live: {
+ enabled: true,
+ allowReplay: false,
+ maxDuration: -1,
+ maxInstanceLives: -1,
+ maxUserLives: 50,
+ transcoding: {
+ enabled: true,
+ threads: 4,
+ profile: 'default',
+ resolutions: {
+ '240p': true,
+ '360p': true,
+ '480p': true,
+ '720p': true,
+ '1080p': true,
+ '1440p': true,
+ '2160p': true
+ }
+ }
+ },
+ import: {
+ videos: {
+ concurrency: 3,
+ http: {
+ enabled: false
+ },
+ torrent: {
+ enabled: false
+ }
+ }
+ },
+ trending: {
+ videos: {
+ algorithms: {
+ enabled: [ 'best', 'hot', 'most-viewed', 'most-liked' ],
+ default: 'hot'
+ }
+ }
+ },
+ autoBlacklist: {
+ videos: {
+ ofUsers: {
+ enabled: false
+ }
+ }
+ },
+ followers: {
+ instance: {
+ enabled: true,
+ manualApproval: false
+ }
+ },
+ followings: {
+ instance: {
+ autoFollowBack: {
+ enabled: false
+ },
+ autoFollowIndex: {
+ indexUrl: 'https://instances.joinpeertube.org/api/v1/instances/hosts',
+ enabled: false
+ }
+ }
+ },
+ broadcastMessage: {
+ enabled: true,
+ level: 'warning',
+ message: 'hello',
+ dismissable: true
+ },
+ search: {
+ remoteUri: {
+ users: true,
+ anonymous: true
+ },
+ searchIndex: {
+ enabled: true,
+ url: 'https://search.joinpeertube.org',
+ disableLocalSearch: true,
+ isDefaultSearch: true
+ }
+ }
+ }
+
+ merge(newCustomConfig, options.newConfig)
+
+ return this.updateCustomConfig({ ...options, newCustomConfig })
+ }
+}
+++ /dev/null
-import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../requests/requests'
-import { CustomConfig } from '../../models/server/custom-config.model'
-import { DeepPartial, HttpStatusCode } from '@shared/core-utils'
-import { merge } from 'lodash'
-
-function getConfig (url: string) {
- const path = '/api/v1/config'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getAbout (url: string) {
- const path = '/api/v1/config/about'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getCustomConfig (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/config/custom'
-
- return makeGetRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function updateCustomConfig (url: string, token: string, newCustomConfig: CustomConfig, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/config/custom'
-
- return makePutBodyRequest({
- url,
- token,
- path,
- fields: newCustomConfig,
- statusCodeExpected
- })
-}
-
-function updateCustomSubConfig (url: string, token: string, newConfig: DeepPartial<CustomConfig>) {
- const updateParams: CustomConfig = {
- instance: {
- name: 'PeerTube updated',
- shortDescription: 'my short description',
- description: 'my super description',
- terms: 'my super terms',
- codeOfConduct: 'my super coc',
-
- creationReason: 'my super creation reason',
- moderationInformation: 'my super moderation information',
- administrator: 'Kuja',
- maintenanceLifetime: 'forever',
- businessModel: 'my super business model',
- hardwareInformation: '2vCore 3GB RAM',
-
- languages: [ 'en', 'es' ],
- categories: [ 1, 2 ],
-
- isNSFW: true,
- defaultNSFWPolicy: 'blur',
-
- defaultClientRoute: '/videos/recently-added',
-
- customizations: {
- javascript: 'alert("coucou")',
- css: 'body { background-color: red; }'
- }
- },
- theme: {
- default: 'default'
- },
- services: {
- twitter: {
- username: '@MySuperUsername',
- whitelisted: true
- }
- },
- cache: {
- previews: {
- size: 2
- },
- captions: {
- size: 3
- },
- torrents: {
- size: 4
- }
- },
- signup: {
- enabled: false,
- limit: 5,
- requiresEmailVerification: false,
- minimumAge: 16
- },
- admin: {
- email: 'superadmin1@example.com'
- },
- contactForm: {
- enabled: true
- },
- user: {
- videoQuota: 5242881,
- videoQuotaDaily: 318742
- },
- transcoding: {
- enabled: true,
- allowAdditionalExtensions: true,
- allowAudioFiles: true,
- threads: 1,
- concurrency: 3,
- profile: 'default',
- resolutions: {
- '0p': false,
- '240p': false,
- '360p': true,
- '480p': true,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- webtorrent: {
- enabled: true
- },
- hls: {
- enabled: false
- }
- },
- live: {
- enabled: true,
- allowReplay: false,
- maxDuration: -1,
- maxInstanceLives: -1,
- maxUserLives: 50,
- transcoding: {
- enabled: true,
- threads: 4,
- profile: 'default',
- resolutions: {
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- }
- }
- },
- import: {
- videos: {
- concurrency: 3,
- http: {
- enabled: false
- },
- torrent: {
- enabled: false
- }
- }
- },
- trending: {
- videos: {
- algorithms: {
- enabled: [ 'best', 'hot', 'most-viewed', 'most-liked' ],
- default: 'hot'
- }
- }
- },
- autoBlacklist: {
- videos: {
- ofUsers: {
- enabled: false
- }
- }
- },
- followers: {
- instance: {
- enabled: true,
- manualApproval: false
- }
- },
- followings: {
- instance: {
- autoFollowBack: {
- enabled: false
- },
- autoFollowIndex: {
- indexUrl: 'https://instances.joinpeertube.org/api/v1/instances/hosts',
- enabled: false
- }
- }
- },
- broadcastMessage: {
- enabled: true,
- level: 'warning',
- message: 'hello',
- dismissable: true
- },
- search: {
- remoteUri: {
- users: true,
- anonymous: true
- },
- searchIndex: {
- enabled: true,
- url: 'https://search.joinpeertube.org',
- disableLocalSearch: true,
- isDefaultSearch: true
- }
- }
- }
-
- merge(updateParams, newConfig)
-
- return updateCustomConfig(url, token, updateParams)
-}
-
-function getCustomConfigResolutions (enabled: boolean) {
- return {
- '240p': enabled,
- '360p': enabled,
- '480p': enabled,
- '720p': enabled,
- '1080p': enabled,
- '1440p': enabled,
- '2160p': enabled
- }
-}
-
-function deleteCustomConfig (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/config/custom'
-
- return makeDeleteRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getConfig,
- getCustomConfig,
- updateCustomConfig,
- getAbout,
- deleteCustomConfig,
- updateCustomSubConfig,
- getCustomConfigResolutions
-}
--- /dev/null
+import { HttpStatusCode } from '@shared/models'
+import { ContactForm } from '../../models/server'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ContactFormCommand extends AbstractCommand {
+
+ send (options: OverrideCommandOptions & {
+ fromEmail: string
+ fromName: string
+ subject: string
+ body: string
+ }) {
+ const path = '/api/v1/server/contact'
+
+ const body: ContactForm = {
+ fromEmail: options.fromEmail,
+ fromName: options.fromName,
+ subject: options.subject,
+ body: options.body
+ }
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: body,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import * as request from 'supertest'
-import { ContactForm } from '../../models/server'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function sendContactForm (options: {
- url: string
- fromEmail: string
- fromName: string
- subject: string
- body: string
- expectedStatus?: number
-}) {
- const path = '/api/v1/server/contact'
-
- const body: ContactForm = {
- fromEmail: options.fromEmail,
- fromName: options.fromName,
- subject: options.subject,
- body: options.body
- }
- return request(options.url)
- .post(path)
- .send(body)
- .expect(options.expectedStatus || HttpStatusCode.NO_CONTENT_204)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- sendContactForm
-}
--- /dev/null
+import { Debug, HttpStatusCode, SendDebugCommand } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class DebugCommand extends AbstractCommand {
+
+ getDebug (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/server/debug'
+
+ return this.getRequestBody<Debug>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ sendCommand (options: OverrideCommandOptions & {
+ body: SendDebugCommand
+ }) {
+ const { body } = options
+ const path = '/api/v1/server/debug/run-command'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: body,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import { makeGetRequest, makePostBodyRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
-import { SendDebugCommand } from '@shared/models'
-
-function getDebug (url: string, token: string) {
- const path = '/api/v1/server/debug'
-
- return makeGetRequest({
- url,
- path,
- token,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function sendDebugCommand (url: string, token: string, body: SendDebugCommand) {
- const path = '/api/v1/server/debug/run-command'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: body,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getDebug,
- sendDebugCommand
-}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
+
+import { expect } from 'chai'
+import { pathExists, readdir } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { PeerTubeServer } from './server'
+
+async function checkTmpIsEmpty (server: PeerTubeServer) {
+ await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ])
+
+ if (await pathExists(join('test' + server.internalServerNumber, 'tmp', 'hls'))) {
+ await checkDirectoryIsEmpty(server, 'tmp/hls')
+ }
+}
+
+async function checkDirectoryIsEmpty (server: PeerTubeServer, directory: string, exceptions: string[] = []) {
+ const testDirectory = 'test' + server.internalServerNumber
+
+ const directoryPath = join(root(), testDirectory, directory)
+
+ const directoryExists = await pathExists(directoryPath)
+ expect(directoryExists).to.be.true
+
+ const files = await readdir(directoryPath)
+ const filtered = files.filter(f => exceptions.includes(f) === false)
+
+ expect(filtered).to.have.lengthOf(0)
+}
+
+export {
+ checkTmpIsEmpty,
+ checkDirectoryIsEmpty
+}
--- /dev/null
+import { pick } from '@shared/core-utils'
+import { ActivityPubActorType, ActorFollow, FollowState, HttpStatusCode, ResultList, ServerFollowCreate } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+import { PeerTubeServer } from './server'
+
+export class FollowsCommand extends AbstractCommand {
+
+ getFollowers (options: OverrideCommandOptions & {
+ start: number
+ count: number
+ sort: string
+ search?: string
+ actorType?: ActivityPubActorType
+ state?: FollowState
+ }) {
+ const path = '/api/v1/server/followers'
+
+ const query = pick(options, [ 'start', 'count', 'sort', 'search', 'state', 'actorType' ])
+
+ return this.getRequestBody<ResultList<ActorFollow>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getFollowings (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ search?: string
+ actorType?: ActivityPubActorType
+ state?: FollowState
+ } = {}) {
+ const path = '/api/v1/server/following'
+
+ const query = pick(options, [ 'start', 'count', 'sort', 'search', 'state', 'actorType' ])
+
+ return this.getRequestBody<ResultList<ActorFollow>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ follow (options: OverrideCommandOptions & {
+ hosts?: string[]
+ handles?: string[]
+ }) {
+ const path = '/api/v1/server/following'
+
+ const fields: ServerFollowCreate = {}
+
+ if (options.hosts) {
+ fields.hosts = options.hosts.map(f => f.replace(/^http:\/\//, ''))
+ }
+
+ if (options.handles) {
+ fields.handles = options.handles
+ }
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ async unfollow (options: OverrideCommandOptions & {
+ target: PeerTubeServer | string
+ }) {
+ const { target } = options
+
+ const handle = typeof target === 'string'
+ ? target
+ : target.host
+
+ const path = '/api/v1/server/following/' + handle
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ acceptFollower (options: OverrideCommandOptions & {
+ follower: string
+ }) {
+ const path = '/api/v1/server/followers/' + options.follower + '/accept'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ rejectFollower (options: OverrideCommandOptions & {
+ follower: string
+ }) {
+ const path = '/api/v1/server/followers/' + options.follower + '/reject'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ removeFollower (options: OverrideCommandOptions & {
+ follower: PeerTubeServer
+ }) {
+ const path = '/api/v1/server/followers/peertube@' + options.follower.host
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
-import * as request from 'supertest'
-import { ServerInfo } from './servers'
import { waitJobs } from './jobs'
-import { makePostBodyRequest } from '../requests/requests'
-import { ActivityPubActorType, FollowState } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { PeerTubeServer } from './server'
-function getFollowersListPaginationAndSort (options: {
- url: string
- start: number
- count: number
- sort: string
- search?: string
- actorType?: ActivityPubActorType
- state?: FollowState
-}) {
- const { url, start, count, sort, search, state, actorType } = options
- const path = '/api/v1/server/followers'
-
- const query = {
- start,
- count,
- sort,
- search,
- state,
- actorType
- }
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function acceptFollower (url: string, token: string, follower: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/server/followers/' + follower + '/accept'
-
- return makePostBodyRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function rejectFollower (url: string, token: string, follower: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/server/followers/' + follower + '/reject'
-
- return makePostBodyRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function getFollowingListPaginationAndSort (options: {
- url: string
- start: number
- count: number
- sort: string
- search?: string
- actorType?: ActivityPubActorType
- state?: FollowState
-}) {
- const { url, start, count, sort, search, state, actorType } = options
- const path = '/api/v1/server/following'
-
- const query = {
- start,
- count,
- sort,
- search,
- state,
- actorType
- }
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function follow (follower: string, following: string[], accessToken: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/server/following'
-
- const followingHosts = following.map(f => f.replace(/^http:\/\//, ''))
- return request(follower)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .send({ hosts: followingHosts })
- .expect(expectedStatus)
-}
-
-async function unfollow (url: string, accessToken: string, target: ServerInfo, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/server/following/' + target.host
-
- return request(url)
- .delete(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(expectedStatus)
-}
-
-function removeFollower (url: string, accessToken: string, follower: ServerInfo, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/server/followers/peertube@' + follower.host
-
- return request(url)
- .delete(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(expectedStatus)
-}
-
-async function doubleFollow (server1: ServerInfo, server2: ServerInfo) {
+async function doubleFollow (server1: PeerTubeServer, server2: PeerTubeServer) {
await Promise.all([
- follow(server1.url, [ server2.url ], server1.accessToken),
- follow(server2.url, [ server1.url ], server2.accessToken)
+ server1.follows.follow({ hosts: [ server2.url ] }),
+ server2.follows.follow({ hosts: [ server1.url ] })
])
// Wait request propagation
// ---------------------------------------------------------------------------
export {
- getFollowersListPaginationAndSort,
- getFollowingListPaginationAndSort,
- unfollow,
- removeFollower,
- follow,
- doubleFollow,
- acceptFollower,
- rejectFollower
+ doubleFollow
}
--- /dev/null
+export * from './config-command'
+export * from './contact-form-command'
+export * from './debug-command'
+export * from './directories'
+export * from './follows-command'
+export * from './follows'
+export * from './jobs'
+export * from './jobs-command'
+export * from './plugins-command'
+export * from './plugins'
+export * from './redundancy-command'
+export * from './server'
+export * from './servers-command'
+export * from './servers'
+export * from './stats-command'
--- /dev/null
+import { pick } from '@shared/core-utils'
+import { HttpStatusCode } from '@shared/models'
+import { Job, JobState, JobType, ResultList } from '../../models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class JobsCommand extends AbstractCommand {
+
+ getJobsList (options: OverrideCommandOptions & {
+ state?: JobState
+ jobType?: JobType
+ start?: number
+ count?: number
+ sort?: string
+ } = {}) {
+ const path = this.buildJobsUrl(options.state)
+
+ const query = pick(options, [ 'start', 'count', 'sort', 'jobType' ])
+
+ return this.getRequestBody<ResultList<Job>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ private buildJobsUrl (state?: JobState) {
+ let path = '/api/v1/jobs'
+
+ if (state) path += '/' + state
+
+ return path
+ }
+}
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { getDebug, makeGetRequest } from '../../../shared/extra-utils'
-import { Job, JobState, JobType, ServerDebug } from '../../models'
-import { wait } from '../miscs/miscs'
-import { ServerInfo } from './servers'
-function buildJobsUrl (state?: JobState) {
- let path = '/api/v1/jobs'
+import { JobState } from '../../models'
+import { wait } from '../miscs'
+import { PeerTubeServer } from './server'
- if (state) path += '/' + state
-
- return path
-}
-
-function getJobsList (url: string, accessToken: string, state?: JobState) {
- const path = buildJobsUrl(state)
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getJobsListPaginationAndSort (options: {
- url: string
- accessToken: string
- start: number
- count: number
- sort: string
- state?: JobState
- jobType?: JobType
-}) {
- const { url, accessToken, state, start, count, sort, jobType } = options
- const path = buildJobsUrl(state)
-
- const query = {
- start,
- count,
- sort,
- jobType
- }
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- statusCodeExpected: HttpStatusCode.OK_200,
- query
- })
-}
-
-async function waitJobs (serversArg: ServerInfo[] | ServerInfo) {
+async function waitJobs (serversArg: PeerTubeServer[] | PeerTubeServer) {
const pendingJobWait = process.env.NODE_PENDING_JOB_WAIT
? parseInt(process.env.NODE_PENDING_JOB_WAIT, 10)
: 250
- let servers: ServerInfo[]
+ let servers: PeerTubeServer[]
- if (Array.isArray(serversArg) === false) servers = [ serversArg as ServerInfo ]
- else servers = serversArg as ServerInfo[]
+ if (Array.isArray(serversArg) === false) servers = [ serversArg as PeerTubeServer ]
+ else servers = serversArg as PeerTubeServer[]
const states: JobState[] = [ 'waiting', 'active', 'delayed' ]
const repeatableJobs = [ 'videos-views', 'activitypub-cleaner' ]
// Check if each server has pending request
for (const server of servers) {
for (const state of states) {
- const p = getJobsListPaginationAndSort({
- url: server.url,
- accessToken: server.accessToken,
- state: state,
+ const p = server.jobs.getJobsList({
+ state,
start: 0,
count: 10,
sort: '-createdAt'
- }).then(res => res.body.data)
- .then((jobs: Job[]) => jobs.filter(j => !repeatableJobs.includes(j.type)))
+ }).then(body => body.data)
+ .then(jobs => jobs.filter(j => !repeatableJobs.includes(j.type)))
.then(jobs => {
if (jobs.length !== 0) {
pendingRequests = true
tasks.push(p)
}
- const p = getDebug(server.url, server.accessToken)
- .then(res => res.body)
- .then((obj: ServerDebug) => {
+ const p = server.debug.getDebug()
+ .then(obj => {
if (obj.activityPubMessagesWaiting !== 0) {
pendingRequests = true
}
// ---------------------------------------------------------------------------
export {
- getJobsList,
- waitJobs,
- getJobsListPaginationAndSort
+ waitJobs
}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
+
+import { readJSON, writeJSON } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import {
+ HttpStatusCode,
+ PeerTubePlugin,
+ PeerTubePluginIndex,
+ PeertubePluginIndexList,
+ PluginPackageJson,
+ PluginTranslation,
+ PluginType,
+ PublicServerSetting,
+ RegisteredServerSettings,
+ ResultList
+} from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class PluginsCommand extends AbstractCommand {
+
+ static getPluginTestPath (suffix = '') {
+ return join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test' + suffix)
+ }
+
+ list (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ pluginType?: PluginType
+ uninstalled?: boolean
+ }) {
+ const { start, count, sort, pluginType, uninstalled } = options
+ const path = '/api/v1/plugins'
+
+ return this.getRequestBody<ResultList<PeerTubePlugin>>({
+ ...options,
+
+ path,
+ query: {
+ start,
+ count,
+ sort,
+ pluginType,
+ uninstalled
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listAvailable (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ pluginType?: PluginType
+ currentPeerTubeEngine?: string
+ search?: string
+ expectedStatus?: HttpStatusCode
+ }) {
+ const { start, count, sort, pluginType, search, currentPeerTubeEngine } = options
+ const path = '/api/v1/plugins/available'
+
+ const query: PeertubePluginIndexList = {
+ start,
+ count,
+ sort,
+ pluginType,
+ currentPeerTubeEngine,
+ search
+ }
+
+ return this.getRequestBody<ResultList<PeerTubePluginIndex>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ get (options: OverrideCommandOptions & {
+ npmName: string
+ }) {
+ const path = '/api/v1/plugins/' + options.npmName
+
+ return this.getRequestBody<PeerTubePlugin>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ updateSettings (options: OverrideCommandOptions & {
+ npmName: string
+ settings: any
+ }) {
+ const { npmName, settings } = options
+ const path = '/api/v1/plugins/' + npmName + '/settings'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: { settings },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ getRegisteredSettings (options: OverrideCommandOptions & {
+ npmName: string
+ }) {
+ const path = '/api/v1/plugins/' + options.npmName + '/registered-settings'
+
+ return this.getRequestBody<RegisteredServerSettings>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getPublicSettings (options: OverrideCommandOptions & {
+ npmName: string
+ }) {
+ const { npmName } = options
+ const path = '/api/v1/plugins/' + npmName + '/public-settings'
+
+ return this.getRequestBody<PublicServerSetting>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getTranslations (options: OverrideCommandOptions & {
+ locale: string
+ }) {
+ const { locale } = options
+ const path = '/plugins/translations/' + locale + '.json'
+
+ return this.getRequestBody<PluginTranslation>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ install (options: OverrideCommandOptions & {
+ path?: string
+ npmName?: string
+ }) {
+ const { npmName, path } = options
+ const apiPath = '/api/v1/plugins/install'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path: apiPath,
+ fields: { npmName, path },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ update (options: OverrideCommandOptions & {
+ path?: string
+ npmName?: string
+ }) {
+ const { npmName, path } = options
+ const apiPath = '/api/v1/plugins/update'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path: apiPath,
+ fields: { npmName, path },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ uninstall (options: OverrideCommandOptions & {
+ npmName: string
+ }) {
+ const { npmName } = options
+ const apiPath = '/api/v1/plugins/uninstall'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path: apiPath,
+ fields: { npmName },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ getCSS (options: OverrideCommandOptions = {}) {
+ const path = '/plugins/global.css'
+
+ return this.getRequestText({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getExternalAuth (options: OverrideCommandOptions & {
+ npmName: string
+ npmVersion: string
+ authName: string
+ query?: any
+ }) {
+ const { npmName, npmVersion, authName, query } = options
+
+ const path = '/plugins/' + npmName + '/' + npmVersion + '/auth/' + authName
+
+ return this.getRequest({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200,
+ redirects: 0
+ })
+ }
+
+ updatePackageJSON (npmName: string, json: any) {
+ const path = this.getPackageJSONPath(npmName)
+
+ return writeJSON(path, json)
+ }
+
+ getPackageJSON (npmName: string): Promise<PluginPackageJson> {
+ const path = this.getPackageJSONPath(npmName)
+
+ return readJSON(path)
+ }
+
+ private getPackageJSONPath (npmName: string) {
+ return this.server.servers.buildDirectory(join('plugins', 'node_modules', npmName, 'package.json'))
+ }
+}
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
-import { readJSON, writeJSON } from 'fs-extra'
-import { join } from 'path'
-import { RegisteredServerSettings } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { PeertubePluginIndexList } from '../../models/plugins/plugin-index/peertube-plugin-index-list.model'
-import { PluginType } from '../../models/plugins/plugin.type'
-import { buildServerDirectory, root } from '../miscs/miscs'
-import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
-import { ServerInfo } from './servers'
+import { PeerTubeServer } from '../server/server'
-function listPlugins (parameters: {
- url: string
- accessToken: string
- start?: number
- count?: number
- sort?: string
- pluginType?: PluginType
- uninstalled?: boolean
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, start, count, sort, pluginType, uninstalled, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/plugins'
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- query: {
- start,
- count,
- sort,
- pluginType,
- uninstalled
- },
- statusCodeExpected: expectedStatus
- })
-}
-
-function listAvailablePlugins (parameters: {
- url: string
- accessToken: string
- start?: number
- count?: number
- sort?: string
- pluginType?: PluginType
- currentPeerTubeEngine?: string
- search?: string
- expectedStatus?: HttpStatusCode
-}) {
- const {
- url,
- accessToken,
- start,
- count,
- sort,
- pluginType,
- search,
- currentPeerTubeEngine,
- expectedStatus = HttpStatusCode.OK_200
- } = parameters
- const path = '/api/v1/plugins/available'
-
- const query: PeertubePluginIndexList = {
- start,
- count,
- sort,
- pluginType,
- currentPeerTubeEngine,
- search
- }
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- query,
- statusCodeExpected: expectedStatus
- })
-}
-
-function getPlugin (parameters: {
- url: string
- accessToken: string
- npmName: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/plugins/' + npmName
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- statusCodeExpected: expectedStatus
- })
-}
-
-function updatePluginSettings (parameters: {
- url: string
- accessToken: string
- npmName: string
- settings: any
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, settings, expectedStatus = HttpStatusCode.NO_CONTENT_204 } = parameters
- const path = '/api/v1/plugins/' + npmName + '/settings'
-
- return makePutBodyRequest({
- url,
- path,
- token: accessToken,
- fields: { settings },
- statusCodeExpected: expectedStatus
- })
-}
-
-function getPluginRegisteredSettings (parameters: {
- url: string
- accessToken: string
- npmName: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/plugins/' + npmName + '/registered-settings'
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- statusCodeExpected: expectedStatus
- })
-}
-
-async function testHelloWorldRegisteredSettings (server: ServerInfo) {
- const res = await getPluginRegisteredSettings({
- url: server.url,
- accessToken: server.accessToken,
- npmName: 'peertube-plugin-hello-world'
- })
-
- const registeredSettings = (res.body as RegisteredServerSettings).registeredSettings
+async function testHelloWorldRegisteredSettings (server: PeerTubeServer) {
+ const body = await server.plugins.getRegisteredSettings({ npmName: 'peertube-plugin-hello-world' })
+ const registeredSettings = body.registeredSettings
expect(registeredSettings).to.have.length.at.least(1)
const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name')
expect(adminNameSettings).to.not.be.undefined
}
-function getPublicSettings (parameters: {
- url: string
- npmName: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, npmName, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/plugins/' + npmName + '/public-settings'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: expectedStatus
- })
-}
-
-function getPluginTranslations (parameters: {
- url: string
- locale: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, locale, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/plugins/translations/' + locale + '.json'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: expectedStatus
- })
-}
-
-function installPlugin (parameters: {
- url: string
- accessToken: string
- path?: string
- npmName?: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, path, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const apiPath = '/api/v1/plugins/install'
-
- return makePostBodyRequest({
- url,
- path: apiPath,
- token: accessToken,
- fields: { npmName, path },
- statusCodeExpected: expectedStatus
- })
-}
-
-function updatePlugin (parameters: {
- url: string
- accessToken: string
- path?: string
- npmName?: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, path, expectedStatus = HttpStatusCode.OK_200 } = parameters
- const apiPath = '/api/v1/plugins/update'
-
- return makePostBodyRequest({
- url,
- path: apiPath,
- token: accessToken,
- fields: { npmName, path },
- statusCodeExpected: expectedStatus
- })
-}
-
-function uninstallPlugin (parameters: {
- url: string
- accessToken: string
- npmName: string
- expectedStatus?: HttpStatusCode
-}) {
- const { url, accessToken, npmName, expectedStatus = HttpStatusCode.NO_CONTENT_204 } = parameters
- const apiPath = '/api/v1/plugins/uninstall'
-
- return makePostBodyRequest({
- url,
- path: apiPath,
- token: accessToken,
- fields: { npmName },
- statusCodeExpected: expectedStatus
- })
-}
-
-function getPluginsCSS (url: string) {
- const path = '/plugins/global.css'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getPackageJSONPath (server: ServerInfo, npmName: string) {
- return buildServerDirectory(server, join('plugins', 'node_modules', npmName, 'package.json'))
-}
-
-function updatePluginPackageJSON (server: ServerInfo, npmName: string, json: any) {
- const path = getPackageJSONPath(server, npmName)
-
- return writeJSON(path, json)
-}
-
-function getPluginPackageJSON (server: ServerInfo, npmName: string) {
- const path = getPackageJSONPath(server, npmName)
-
- return readJSON(path)
-}
-
-function getPluginTestPath (suffix = '') {
- return join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test' + suffix)
-}
-
-function getExternalAuth (options: {
- url: string
- npmName: string
- npmVersion: string
- authName: string
- query?: any
- statusCodeExpected?: HttpStatusCode
-}) {
- const { url, npmName, npmVersion, authName, statusCodeExpected, query } = options
-
- const path = '/plugins/' + npmName + '/' + npmVersion + '/auth/' + authName
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected: statusCodeExpected || HttpStatusCode.OK_200,
- redirects: 0
- })
-}
-
export {
- listPlugins,
- listAvailablePlugins,
- installPlugin,
- getPluginTranslations,
- getPluginsCSS,
- updatePlugin,
- getPlugin,
- uninstallPlugin,
- testHelloWorldRegisteredSettings,
- updatePluginSettings,
- getPluginRegisteredSettings,
- getPackageJSONPath,
- updatePluginPackageJSON,
- getPluginPackageJSON,
- getPluginTestPath,
- getPublicSettings,
- getExternalAuth
+ testHelloWorldRegisteredSettings
}
--- /dev/null
+import { HttpStatusCode, ResultList, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class RedundancyCommand extends AbstractCommand {
+
+ updateRedundancy (options: OverrideCommandOptions & {
+ host: string
+ redundancyAllowed: boolean
+ }) {
+ const { host, redundancyAllowed } = options
+ const path = '/api/v1/server/redundancy/' + host
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: { redundancyAllowed },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ listVideos (options: OverrideCommandOptions & {
+ target: VideoRedundanciesTarget
+ start?: number
+ count?: number
+ sort?: string
+ }) {
+ const path = '/api/v1/server/redundancy/videos'
+
+ const { target, start, count, sort } = options
+
+ return this.getRequestBody<ResultList<VideoRedundancy>>({
+ ...options,
+
+ path,
+
+ query: {
+ start: start ?? 0,
+ count: count ?? 5,
+ sort: sort ?? 'name',
+ target
+ },
+
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ addVideo (options: OverrideCommandOptions & {
+ videoId: number
+ }) {
+ const path = '/api/v1/server/redundancy/videos'
+ const { videoId } = options
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { videoId },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ removeVideo (options: OverrideCommandOptions & {
+ redundancyId: number
+ }) {
+ const { redundancyId } = options
+ const path = '/api/v1/server/redundancy/videos/' + redundancyId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
-import { VideoRedundanciesTarget } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function updateRedundancy (
- url: string,
- accessToken: string,
- host: string,
- redundancyAllowed: boolean,
- expectedStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/server/redundancy/' + host
-
- return makePutBodyRequest({
- url,
- path,
- token: accessToken,
- fields: { redundancyAllowed },
- statusCodeExpected: expectedStatus
- })
-}
-
-function listVideoRedundancies (options: {
- url: string
- accessToken: string
- target: VideoRedundanciesTarget
- start?: number
- count?: number
- sort?: string
- statusCodeExpected?: HttpStatusCode
-}) {
- const path = '/api/v1/server/redundancy/videos'
-
- const { url, accessToken, target, statusCodeExpected, start, count, sort } = options
-
- return makeGetRequest({
- url,
- token: accessToken,
- path,
- query: {
- start: start ?? 0,
- count: count ?? 5,
- sort: sort ?? 'name',
- target
- },
- statusCodeExpected: statusCodeExpected || HttpStatusCode.OK_200
- })
-}
-
-function addVideoRedundancy (options: {
- url: string
- accessToken: string
- videoId: number
-}) {
- const path = '/api/v1/server/redundancy/videos'
- const { url, accessToken, videoId } = options
-
- return makePostBodyRequest({
- url,
- token: accessToken,
- path,
- fields: { videoId },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function removeVideoRedundancy (options: {
- url: string
- accessToken: string
- redundancyId: number
-}) {
- const { url, accessToken, redundancyId } = options
- const path = '/api/v1/server/redundancy/videos/' + redundancyId
-
- return makeDeleteRequest({
- url,
- token: accessToken,
- path,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-export {
- updateRedundancy,
- listVideoRedundancies,
- addVideoRedundancy,
- removeVideoRedundancy
-}
--- /dev/null
+import { ChildProcess, fork } from 'child_process'
+import { copy } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { randomInt } from '@shared/core-utils'
+import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '../../models/videos'
+import { BulkCommand } from '../bulk'
+import { CLICommand } from '../cli'
+import { CustomPagesCommand } from '../custom-pages'
+import { FeedCommand } from '../feeds'
+import { LogsCommand } from '../logs'
+import { parallelTests, SQLCommand } from '../miscs'
+import { AbusesCommand } from '../moderation'
+import { OverviewsCommand } from '../overviews'
+import { SearchCommand } from '../search'
+import { SocketIOCommand } from '../socket'
+import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand, UsersCommand } from '../users'
+import {
+ BlacklistCommand,
+ CaptionsCommand,
+ ChangeOwnershipCommand,
+ ChannelsCommand,
+ HistoryCommand,
+ ImportsCommand,
+ LiveCommand,
+ PlaylistsCommand,
+ ServicesCommand,
+ StreamingPlaylistsCommand,
+ VideosCommand
+} from '../videos'
+import { CommentsCommand } from '../videos/comments-command'
+import { ConfigCommand } from './config-command'
+import { ContactFormCommand } from './contact-form-command'
+import { DebugCommand } from './debug-command'
+import { FollowsCommand } from './follows-command'
+import { JobsCommand } from './jobs-command'
+import { PluginsCommand } from './plugins-command'
+import { RedundancyCommand } from './redundancy-command'
+import { ServersCommand } from './servers-command'
+import { StatsCommand } from './stats-command'
+
+export type RunServerOptions = {
+ hideLogs?: boolean
+ nodeArgs?: string[]
+ peertubeArgs?: string[]
+}
+
+export class PeerTubeServer {
+ app?: ChildProcess
+
+ url: string
+ host?: string
+ hostname?: string
+ port?: number
+
+ rtmpPort?: number
+
+ parallel?: boolean
+ internalServerNumber: number
+
+ serverNumber?: number
+ customConfigFile?: string
+
+ store?: {
+ client?: {
+ id?: string
+ secret?: string
+ }
+
+ user?: {
+ username: string
+ password: string
+ email?: string
+ }
+
+ channel?: VideoChannel
+
+ video?: Video
+ videoCreated?: VideoCreateResult
+ videoDetails?: VideoDetails
+
+ videos?: { id: number, uuid: string }[]
+ }
+
+ accessToken?: string
+ refreshToken?: string
+
+ bulk?: BulkCommand
+ cli?: CLICommand
+ customPage?: CustomPagesCommand
+ feed?: FeedCommand
+ logs?: LogsCommand
+ abuses?: AbusesCommand
+ overviews?: OverviewsCommand
+ search?: SearchCommand
+ contactForm?: ContactFormCommand
+ debug?: DebugCommand
+ follows?: FollowsCommand
+ jobs?: JobsCommand
+ plugins?: PluginsCommand
+ redundancy?: RedundancyCommand
+ stats?: StatsCommand
+ config?: ConfigCommand
+ socketIO?: SocketIOCommand
+ accounts?: AccountsCommand
+ blocklist?: BlocklistCommand
+ subscriptions?: SubscriptionsCommand
+ live?: LiveCommand
+ services?: ServicesCommand
+ blacklist?: BlacklistCommand
+ captions?: CaptionsCommand
+ changeOwnership?: ChangeOwnershipCommand
+ playlists?: PlaylistsCommand
+ history?: HistoryCommand
+ imports?: ImportsCommand
+ streamingPlaylists?: StreamingPlaylistsCommand
+ channels?: ChannelsCommand
+ comments?: CommentsCommand
+ sql?: SQLCommand
+ notifications?: NotificationsCommand
+ servers?: ServersCommand
+ login?: LoginCommand
+ users?: UsersCommand
+ videos?: VideosCommand
+
+ constructor (options: { serverNumber: number } | { url: string }) {
+ if ((options as any).url) {
+ this.setUrl((options as any).url)
+ } else {
+ this.setServerNumber((options as any).serverNumber)
+ }
+
+ this.store = {
+ client: {
+ id: null,
+ secret: null
+ },
+ user: {
+ username: null,
+ password: null
+ }
+ }
+
+ this.assignCommands()
+ }
+
+ setServerNumber (serverNumber: number) {
+ this.serverNumber = serverNumber
+
+ this.parallel = parallelTests()
+
+ this.internalServerNumber = this.parallel ? this.randomServer() : this.serverNumber
+ this.rtmpPort = this.parallel ? this.randomRTMP() : 1936
+ this.port = 9000 + this.internalServerNumber
+
+ this.url = `http://localhost:${this.port}`
+ this.host = `localhost:${this.port}`
+ this.hostname = 'localhost'
+ }
+
+ setUrl (url: string) {
+ const parsed = new URL(url)
+
+ this.url = url
+ this.host = parsed.host
+ this.hostname = parsed.hostname
+ this.port = parseInt(parsed.port)
+ }
+
+ async flushAndRun (configOverride?: Object, options: RunServerOptions = {}) {
+ await ServersCommand.flushTests(this.internalServerNumber)
+
+ return this.run(configOverride, options)
+ }
+
+ async run (configOverrideArg?: any, options: RunServerOptions = {}) {
+ // These actions are async so we need to be sure that they have both been done
+ const serverRunString = {
+ 'HTTP server listening': false
+ }
+ const key = 'Database peertube_test' + this.internalServerNumber + ' is ready'
+ serverRunString[key] = false
+
+ const regexps = {
+ client_id: 'Client id: (.+)',
+ client_secret: 'Client secret: (.+)',
+ user_username: 'Username: (.+)',
+ user_password: 'User password: (.+)'
+ }
+
+ await this.assignCustomConfigFile()
+
+ const configOverride = this.buildConfigOverride()
+
+ if (configOverrideArg !== undefined) {
+ Object.assign(configOverride, configOverrideArg)
+ }
+
+ // Share the environment
+ const env = Object.create(process.env)
+ env['NODE_ENV'] = 'test'
+ env['NODE_APP_INSTANCE'] = this.internalServerNumber.toString()
+ env['NODE_CONFIG'] = JSON.stringify(configOverride)
+
+ const forkOptions = {
+ silent: true,
+ env,
+ detached: true,
+ execArgv: options.nodeArgs || []
+ }
+
+ return new Promise<void>(res => {
+ const self = this
+
+ this.app = fork(join(root(), 'dist', 'server.js'), options.peertubeArgs || [], forkOptions)
+ this.app.stdout.on('data', function onStdout (data) {
+ let dontContinue = false
+
+ // Capture things if we want to
+ for (const key of Object.keys(regexps)) {
+ const regexp = regexps[key]
+ const matches = data.toString().match(regexp)
+ if (matches !== null) {
+ if (key === 'client_id') self.store.client.id = matches[1]
+ else if (key === 'client_secret') self.store.client.secret = matches[1]
+ else if (key === 'user_username') self.store.user.username = matches[1]
+ else if (key === 'user_password') self.store.user.password = matches[1]
+ }
+ }
+
+ // Check if all required sentences are here
+ for (const key of Object.keys(serverRunString)) {
+ if (data.toString().indexOf(key) !== -1) serverRunString[key] = true
+ if (serverRunString[key] === false) dontContinue = true
+ }
+
+ // If no, there is maybe one thing not already initialized (client/user credentials generation...)
+ if (dontContinue === true) return
+
+ if (options.hideLogs === false) {
+ console.log(data.toString())
+ } else {
+ self.app.stdout.removeListener('data', onStdout)
+ }
+
+ process.on('exit', () => {
+ try {
+ process.kill(self.app.pid)
+ } catch { /* empty */ }
+ })
+
+ res()
+ })
+ })
+ }
+
+ async kill () {
+ if (!this.app) return
+
+ await this.sql.cleanup()
+
+ process.kill(-this.app.pid)
+
+ this.app = null
+ }
+
+ private randomServer () {
+ const low = 10
+ const high = 10000
+
+ return randomInt(low, high)
+ }
+
+ private randomRTMP () {
+ const low = 1900
+ const high = 2100
+
+ return randomInt(low, high)
+ }
+
+ private async assignCustomConfigFile () {
+ if (this.internalServerNumber === this.serverNumber) return
+
+ const basePath = join(root(), 'config')
+
+ const tmpConfigFile = join(basePath, `test-${this.internalServerNumber}.yaml`)
+ await copy(join(basePath, `test-${this.serverNumber}.yaml`), tmpConfigFile)
+
+ this.customConfigFile = tmpConfigFile
+ }
+
+ private buildConfigOverride () {
+ if (!this.parallel) return {}
+
+ return {
+ listen: {
+ port: this.port
+ },
+ webserver: {
+ port: this.port
+ },
+ database: {
+ suffix: '_test' + this.internalServerNumber
+ },
+ storage: {
+ tmp: `test${this.internalServerNumber}/tmp/`,
+ avatars: `test${this.internalServerNumber}/avatars/`,
+ videos: `test${this.internalServerNumber}/videos/`,
+ streaming_playlists: `test${this.internalServerNumber}/streaming-playlists/`,
+ redundancy: `test${this.internalServerNumber}/redundancy/`,
+ logs: `test${this.internalServerNumber}/logs/`,
+ previews: `test${this.internalServerNumber}/previews/`,
+ thumbnails: `test${this.internalServerNumber}/thumbnails/`,
+ torrents: `test${this.internalServerNumber}/torrents/`,
+ captions: `test${this.internalServerNumber}/captions/`,
+ cache: `test${this.internalServerNumber}/cache/`,
+ plugins: `test${this.internalServerNumber}/plugins/`
+ },
+ admin: {
+ email: `admin${this.internalServerNumber}@example.com`
+ },
+ live: {
+ rtmp: {
+ port: this.rtmpPort
+ }
+ }
+ }
+ }
+
+ private assignCommands () {
+ this.bulk = new BulkCommand(this)
+ this.cli = new CLICommand(this)
+ this.customPage = new CustomPagesCommand(this)
+ this.feed = new FeedCommand(this)
+ this.logs = new LogsCommand(this)
+ this.abuses = new AbusesCommand(this)
+ this.overviews = new OverviewsCommand(this)
+ this.search = new SearchCommand(this)
+ this.contactForm = new ContactFormCommand(this)
+ this.debug = new DebugCommand(this)
+ this.follows = new FollowsCommand(this)
+ this.jobs = new JobsCommand(this)
+ this.plugins = new PluginsCommand(this)
+ this.redundancy = new RedundancyCommand(this)
+ this.stats = new StatsCommand(this)
+ this.config = new ConfigCommand(this)
+ this.socketIO = new SocketIOCommand(this)
+ this.accounts = new AccountsCommand(this)
+ this.blocklist = new BlocklistCommand(this)
+ this.subscriptions = new SubscriptionsCommand(this)
+ this.live = new LiveCommand(this)
+ this.services = new ServicesCommand(this)
+ this.blacklist = new BlacklistCommand(this)
+ this.captions = new CaptionsCommand(this)
+ this.changeOwnership = new ChangeOwnershipCommand(this)
+ this.playlists = new PlaylistsCommand(this)
+ this.history = new HistoryCommand(this)
+ this.imports = new ImportsCommand(this)
+ this.streamingPlaylists = new StreamingPlaylistsCommand(this)
+ this.channels = new ChannelsCommand(this)
+ this.comments = new CommentsCommand(this)
+ this.sql = new SQLCommand(this)
+ this.notifications = new NotificationsCommand(this)
+ this.servers = new ServersCommand(this)
+ this.login = new LoginCommand(this)
+ this.users = new UsersCommand(this)
+ this.videos = new VideosCommand(this)
+ }
+}
--- /dev/null
+import { exec } from 'child_process'
+import { copy, ensureDir, readFile, remove } from 'fs-extra'
+import { basename, join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { HttpStatusCode } from '@shared/models'
+import { getFileSize, isGithubCI, wait } from '../miscs'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ServersCommand extends AbstractCommand {
+
+ static flushTests (internalServerNumber: number) {
+ return new Promise<void>((res, rej) => {
+ const suffix = ` -- ${internalServerNumber}`
+
+ return exec('npm run clean:server:test' + suffix, (err, _stdout, stderr) => {
+ if (err || stderr) return rej(err || new Error(stderr))
+
+ return res()
+ })
+ })
+ }
+
+ ping (options: OverrideCommandOptions = {}) {
+ return this.getRequestBody({
+ ...options,
+
+ path: '/api/v1/ping',
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ async cleanupTests () {
+ const p: Promise<any>[] = []
+
+ if (isGithubCI()) {
+ await ensureDir('artifacts')
+
+ const origin = this.buildDirectory('logs/peertube.log')
+ const destname = `peertube-${this.server.internalServerNumber}.log`
+ console.log('Saving logs %s.', destname)
+
+ await copy(origin, join('artifacts', destname))
+ }
+
+ if (this.server.parallel) {
+ p.push(ServersCommand.flushTests(this.server.internalServerNumber))
+ }
+
+ if (this.server.customConfigFile) {
+ p.push(remove(this.server.customConfigFile))
+ }
+
+ return p
+ }
+
+ async waitUntilLog (str: string, count = 1, strictCount = true) {
+ const logfile = this.server.servers.buildDirectory('logs/peertube.log')
+
+ while (true) {
+ const buf = await readFile(logfile)
+
+ const matches = buf.toString().match(new RegExp(str, 'g'))
+ if (matches && matches.length === count) return
+ if (matches && strictCount === false && matches.length >= count) return
+
+ await wait(1000)
+ }
+ }
+
+ buildDirectory (directory: string) {
+ return join(root(), 'test' + this.server.internalServerNumber, directory)
+ }
+
+ buildWebTorrentFilePath (fileUrl: string) {
+ return this.buildDirectory(join('videos', basename(fileUrl)))
+ }
+
+ buildFragmentedFilePath (videoUUID: string, fileUrl: string) {
+ return this.buildDirectory(join('streaming-playlists', 'hls', videoUUID, basename(fileUrl)))
+ }
+
+ async getServerFileSize (subPath: string) {
+ const path = this.server.servers.buildDirectory(subPath)
+
+ return getFileSize(path)
+ }
+}
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
+import { ensureDir } from 'fs-extra'
+import { isGithubCI } from '../miscs'
+import { PeerTubeServer, RunServerOptions } from './server'
-import { expect } from 'chai'
-import { ChildProcess, exec, fork } from 'child_process'
-import { copy, ensureDir, pathExists, readdir, readFile, remove } from 'fs-extra'
-import { join } from 'path'
-import { randomInt } from '../../core-utils/miscs/miscs'
-import { VideoChannel } from '../../models/videos'
-import { buildServerDirectory, getFileSize, isGithubCI, root, wait } from '../miscs/miscs'
-import { makeGetRequest } from '../requests/requests'
+async function createSingleServer (serverNumber: number, configOverride?: Object, options: RunServerOptions = {}) {
+ const server = new PeerTubeServer({ serverNumber })
-interface ServerInfo {
- app: ChildProcess
-
- url: string
- host: string
- hostname: string
- port: number
-
- rtmpPort: number
-
- parallel: boolean
- internalServerNumber: number
- serverNumber: number
-
- client: {
- id: string
- secret: string
- }
-
- user: {
- username: string
- password: string
- email?: string
- }
-
- customConfigFile?: string
-
- accessToken?: string
- refreshToken?: string
- videoChannel?: VideoChannel
-
- video?: {
- id: number
- uuid: string
- shortUUID: string
- name?: string
- url?: string
-
- account?: {
- name: string
- }
-
- embedPath?: string
- }
-
- remoteVideo?: {
- id: number
- uuid: string
- }
-
- videos?: { id: number, uuid: string }[]
-}
-
-function parallelTests () {
- return process.env.MOCHA_PARALLEL === 'true'
-}
-
-function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) {
- const apps = []
- let i = 0
-
- return new Promise<ServerInfo[]>(res => {
- function anotherServerDone (serverNumber, app) {
- apps[serverNumber - 1] = app
- i++
- if (i === totalServers) {
- return res(apps)
- }
- }
-
- for (let j = 1; j <= totalServers; j++) {
- flushAndRunServer(j, configOverride).then(app => anotherServerDone(j, app))
- }
- })
-}
-
-function flushTests (serverNumber?: number) {
- return new Promise<void>((res, rej) => {
- const suffix = serverNumber ? ` -- ${serverNumber}` : ''
-
- return exec('npm run clean:server:test' + suffix, (err, _stdout, stderr) => {
- if (err || stderr) return rej(err || new Error(stderr))
-
- return res()
- })
- })
-}
-
-function randomServer () {
- const low = 10
- const high = 10000
-
- return randomInt(low, high)
-}
-
-function randomRTMP () {
- const low = 1900
- const high = 2100
-
- return randomInt(low, high)
-}
-
-type RunServerOptions = {
- hideLogs?: boolean
- execArgv?: string[]
-}
-
-async function flushAndRunServer (serverNumber: number, configOverride?: Object, args = [], options: RunServerOptions = {}) {
- const parallel = parallelTests()
-
- const internalServerNumber = parallel ? randomServer() : serverNumber
- const rtmpPort = parallel ? randomRTMP() : 1936
- const port = 9000 + internalServerNumber
-
- await flushTests(internalServerNumber)
-
- const server: ServerInfo = {
- app: null,
- port,
- internalServerNumber,
- rtmpPort,
- parallel,
- serverNumber,
- url: `http://localhost:${port}`,
- host: `localhost:${port}`,
- hostname: 'localhost',
- client: {
- id: null,
- secret: null
- },
- user: {
- username: null,
- password: null
- }
- }
-
- return runServer(server, configOverride, args, options)
-}
-
-async function runServer (server: ServerInfo, configOverrideArg?: any, args = [], options: RunServerOptions = {}) {
- // These actions are async so we need to be sure that they have both been done
- const serverRunString = {
- 'HTTP server listening': false
- }
- const key = 'Database peertube_test' + server.internalServerNumber + ' is ready'
- serverRunString[key] = false
-
- const regexps = {
- client_id: 'Client id: (.+)',
- client_secret: 'Client secret: (.+)',
- user_username: 'Username: (.+)',
- user_password: 'User password: (.+)'
- }
-
- if (server.internalServerNumber !== server.serverNumber) {
- const basePath = join(root(), 'config')
-
- const tmpConfigFile = join(basePath, `test-${server.internalServerNumber}.yaml`)
- await copy(join(basePath, `test-${server.serverNumber}.yaml`), tmpConfigFile)
-
- server.customConfigFile = tmpConfigFile
- }
-
- const configOverride: any = {}
-
- if (server.parallel) {
- Object.assign(configOverride, {
- listen: {
- port: server.port
- },
- webserver: {
- port: server.port
- },
- database: {
- suffix: '_test' + server.internalServerNumber
- },
- storage: {
- tmp: `test${server.internalServerNumber}/tmp/`,
- avatars: `test${server.internalServerNumber}/avatars/`,
- videos: `test${server.internalServerNumber}/videos/`,
- streaming_playlists: `test${server.internalServerNumber}/streaming-playlists/`,
- redundancy: `test${server.internalServerNumber}/redundancy/`,
- logs: `test${server.internalServerNumber}/logs/`,
- previews: `test${server.internalServerNumber}/previews/`,
- thumbnails: `test${server.internalServerNumber}/thumbnails/`,
- torrents: `test${server.internalServerNumber}/torrents/`,
- captions: `test${server.internalServerNumber}/captions/`,
- cache: `test${server.internalServerNumber}/cache/`,
- plugins: `test${server.internalServerNumber}/plugins/`
- },
- admin: {
- email: `admin${server.internalServerNumber}@example.com`
- },
- live: {
- rtmp: {
- port: server.rtmpPort
- }
- }
- })
- }
-
- if (configOverrideArg !== undefined) {
- Object.assign(configOverride, configOverrideArg)
- }
-
- // Share the environment
- const env = Object.create(process.env)
- env['NODE_ENV'] = 'test'
- env['NODE_APP_INSTANCE'] = server.internalServerNumber.toString()
- env['NODE_CONFIG'] = JSON.stringify(configOverride)
-
- const forkOptions = {
- silent: true,
- env,
- detached: true,
- execArgv: options.execArgv || []
- }
-
- return new Promise<ServerInfo>(res => {
- server.app = fork(join(root(), 'dist', 'server.js'), args, forkOptions)
- server.app.stdout.on('data', function onStdout (data) {
- let dontContinue = false
-
- // Capture things if we want to
- for (const key of Object.keys(regexps)) {
- const regexp = regexps[key]
- const matches = data.toString().match(regexp)
- if (matches !== null) {
- if (key === 'client_id') server.client.id = matches[1]
- else if (key === 'client_secret') server.client.secret = matches[1]
- else if (key === 'user_username') server.user.username = matches[1]
- else if (key === 'user_password') server.user.password = matches[1]
- }
- }
-
- // Check if all required sentences are here
- for (const key of Object.keys(serverRunString)) {
- if (data.toString().indexOf(key) !== -1) serverRunString[key] = true
- if (serverRunString[key] === false) dontContinue = true
- }
-
- // If no, there is maybe one thing not already initialized (client/user credentials generation...)
- if (dontContinue === true) return
-
- if (options.hideLogs === false) {
- console.log(data.toString())
- } else {
- server.app.stdout.removeListener('data', onStdout)
- }
-
- process.on('exit', () => {
- try {
- process.kill(server.app.pid)
- } catch { /* empty */ }
- })
-
- res(server)
- })
- })
-}
-
-async function reRunServer (server: ServerInfo, configOverride?: any) {
- const newServer = await runServer(server, configOverride)
- server.app = newServer.app
+ await server.flushAndRun(configOverride, options)
return server
}
-async function checkTmpIsEmpty (server: ServerInfo) {
- await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ])
+function createMultipleServers (totalServers: number, configOverride?: Object) {
+ const serverPromises: Promise<PeerTubeServer>[] = []
- if (await pathExists(join('test' + server.internalServerNumber, 'tmp', 'hls'))) {
- await checkDirectoryIsEmpty(server, 'tmp/hls')
+ for (let i = 1; i <= totalServers; i++) {
+ serverPromises.push(createSingleServer(i, configOverride))
}
-}
-
-async function checkDirectoryIsEmpty (server: ServerInfo, directory: string, exceptions: string[] = []) {
- const testDirectory = 'test' + server.internalServerNumber
-
- const directoryPath = join(root(), testDirectory, directory)
- const directoryExists = await pathExists(directoryPath)
- expect(directoryExists).to.be.true
-
- const files = await readdir(directoryPath)
- const filtered = files.filter(f => exceptions.includes(f) === false)
-
- expect(filtered).to.have.lengthOf(0)
+ return Promise.all(serverPromises)
}
-function killallServers (servers: ServerInfo[]) {
- for (const server of servers) {
- if (!server.app) continue
-
- process.kill(-server.app.pid)
- server.app = null
- }
+async function killallServers (servers: PeerTubeServer[]) {
+ return Promise.all(servers.map(s => s.kill()))
}
-async function cleanupTests (servers: ServerInfo[]) {
- killallServers(servers)
+async function cleanupTests (servers: PeerTubeServer[]) {
+ await killallServers(servers)
if (isGithubCI()) {
await ensureDir('artifacts')
}
- const p: Promise<any>[] = []
+ let p: Promise<any>[] = []
for (const server of servers) {
- if (isGithubCI()) {
- const origin = await buildServerDirectory(server, 'logs/peertube.log')
- const destname = `peertube-${server.internalServerNumber}.log`
- console.log('Saving logs %s.', destname)
-
- await copy(origin, join('artifacts', destname))
- }
-
- if (server.parallel) {
- p.push(flushTests(server.internalServerNumber))
- }
-
- if (server.customConfigFile) {
- p.push(remove(server.customConfigFile))
- }
+ p = p.concat(server.servers.cleanupTests())
}
return Promise.all(p)
}
-async function waitUntilLog (server: ServerInfo, str: string, count = 1, strictCount = true) {
- const logfile = buildServerDirectory(server, 'logs/peertube.log')
-
- while (true) {
- const buf = await readFile(logfile)
-
- const matches = buf.toString().match(new RegExp(str, 'g'))
- if (matches && matches.length === count) return
- if (matches && strictCount === false && matches.length >= count) return
-
- await wait(1000)
- }
-}
-
-async function getServerFileSize (server: ServerInfo, subPath: string) {
- const path = buildServerDirectory(server, subPath)
-
- return getFileSize(path)
-}
-
-function makePingRequest (server: ServerInfo) {
- return makeGetRequest({
- url: server.url,
- path: '/api/v1/ping',
- statusCodeExpected: 200
- })
-}
-
// ---------------------------------------------------------------------------
export {
- checkDirectoryIsEmpty,
- checkTmpIsEmpty,
- getServerFileSize,
- ServerInfo,
- parallelTests,
+ createSingleServer,
+ createMultipleServers,
cleanupTests,
- flushAndRunMultipleServers,
- flushTests,
- makePingRequest,
- flushAndRunServer,
- killallServers,
- reRunServer,
- waitUntilLog
+ killallServers
}
--- /dev/null
+import { HttpStatusCode, ServerStats } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class StatsCommand extends AbstractCommand {
+
+ get (options: OverrideCommandOptions & {
+ useCache?: boolean // default false
+ } = {}) {
+ const { useCache = false } = options
+ const path = '/api/v1/server/stats'
+
+ const query = {
+ t: useCache ? undefined : new Date().getTime()
+ }
+
+ return this.getRequestBody<ServerStats>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import { makeGetRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getStats (url: string, useCache = false) {
- const path = '/api/v1/server/stats'
-
- const query = {
- t: useCache ? undefined : new Date().getTime()
- }
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getStats
-}
--- /dev/null
+import { isAbsolute, join } from 'path'
+import { root } from '../miscs/tests'
+import {
+ makeDeleteRequest,
+ makeGetRequest,
+ makePostBodyRequest,
+ makePutBodyRequest,
+ makeUploadRequest,
+ unwrapBody,
+ unwrapText
+} from '../requests/requests'
+import { PeerTubeServer } from '../server/server'
+
+export interface OverrideCommandOptions {
+ token?: string
+ expectedStatus?: number
+}
+
+interface InternalCommonCommandOptions extends OverrideCommandOptions {
+ // Default to server.url
+ url?: string
+
+ path: string
+ // If we automatically send the server token if the token is not provided
+ implicitToken: boolean
+ defaultExpectedStatus: number
+
+ // Common optional request parameters
+ contentType?: string
+ accept?: string
+ redirects?: number
+ range?: string
+ host?: string
+ headers?: { [ name: string ]: string }
+ requestType?: string
+ xForwardedFor?: string
+}
+
+interface InternalGetCommandOptions extends InternalCommonCommandOptions {
+ query?: { [ id: string ]: any }
+}
+
+abstract class AbstractCommand {
+
+ constructor (
+ protected server: PeerTubeServer
+ ) {
+
+ }
+
+ protected getRequestBody <T> (options: InternalGetCommandOptions) {
+ return unwrapBody<T>(this.getRequest(options))
+ }
+
+ protected getRequestText (options: InternalGetCommandOptions) {
+ return unwrapText(this.getRequest(options))
+ }
+
+ protected getRawRequest (options: Omit<InternalGetCommandOptions, 'path'>) {
+ const { url, range } = options
+ const { host, protocol, pathname } = new URL(url)
+
+ return this.getRequest({
+ ...options,
+
+ token: this.buildCommonRequestToken(options),
+ defaultExpectedStatus: this.buildExpectedStatus(options),
+
+ url: `${protocol}//${host}`,
+ path: pathname,
+ range
+ })
+ }
+
+ protected getRequest (options: InternalGetCommandOptions) {
+ const { query } = options
+
+ return makeGetRequest({
+ ...this.buildCommonRequestOptions(options),
+
+ query
+ })
+ }
+
+ protected deleteRequest (options: InternalCommonCommandOptions) {
+ return makeDeleteRequest(this.buildCommonRequestOptions(options))
+ }
+
+ protected putBodyRequest (options: InternalCommonCommandOptions & {
+ fields?: { [ fieldName: string ]: any }
+ }) {
+ const { fields } = options
+
+ return makePutBodyRequest({
+ ...this.buildCommonRequestOptions(options),
+
+ fields
+ })
+ }
+
+ protected postBodyRequest (options: InternalCommonCommandOptions & {
+ fields?: { [ fieldName: string ]: any }
+ }) {
+ const { fields } = options
+
+ return makePostBodyRequest({
+ ...this.buildCommonRequestOptions(options),
+
+ fields
+ })
+ }
+
+ protected postUploadRequest (options: InternalCommonCommandOptions & {
+ fields?: { [ fieldName: string ]: any }
+ attaches?: { [ fieldName: string ]: any }
+ }) {
+ const { fields, attaches } = options
+
+ return makeUploadRequest({
+ ...this.buildCommonRequestOptions(options),
+
+ method: 'POST',
+ fields,
+ attaches
+ })
+ }
+
+ protected putUploadRequest (options: InternalCommonCommandOptions & {
+ fields?: { [ fieldName: string ]: any }
+ attaches?: { [ fieldName: string ]: any }
+ }) {
+ const { fields, attaches } = options
+
+ return makeUploadRequest({
+ ...this.buildCommonRequestOptions(options),
+
+ method: 'PUT',
+ fields,
+ attaches
+ })
+ }
+
+ protected updateImageRequest (options: InternalCommonCommandOptions & {
+ fixture: string
+ fieldname: string
+ }) {
+ const filePath = isAbsolute(options.fixture)
+ ? options.fixture
+ : join(root(), 'server', 'tests', 'fixtures', options.fixture)
+
+ return this.postUploadRequest({
+ ...options,
+
+ fields: {},
+ attaches: { [options.fieldname]: filePath }
+ })
+ }
+
+ protected buildCommonRequestOptions (options: InternalCommonCommandOptions) {
+ const { url, path, redirects, contentType, accept, range, host, headers, requestType, xForwardedFor } = options
+
+ return {
+ url: url ?? this.server.url,
+ path,
+
+ token: this.buildCommonRequestToken(options),
+ expectedStatus: this.buildExpectedStatus(options),
+
+ redirects,
+ contentType,
+ range,
+ host,
+ accept,
+ headers,
+ type: requestType,
+ xForwardedFor
+ }
+ }
+
+ protected buildCommonRequestToken (options: Pick<InternalCommonCommandOptions, 'token' | 'implicitToken'>) {
+ const { token } = options
+
+ const fallbackToken = options.implicitToken
+ ? this.server.accessToken
+ : undefined
+
+ return token !== undefined ? token : fallbackToken
+ }
+
+ protected buildExpectedStatus (options: Pick<InternalCommonCommandOptions, 'expectedStatus' | 'defaultExpectedStatus'>) {
+ const { expectedStatus, defaultExpectedStatus } = options
+
+ return expectedStatus !== undefined ? expectedStatus : defaultExpectedStatus
+ }
+}
+
+export {
+ AbstractCommand
+}
--- /dev/null
+export * from './abstract-command'
--- /dev/null
+export * from './socket-io-command'
--- /dev/null
+import { io } from 'socket.io-client'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class SocketIOCommand extends AbstractCommand {
+
+ getUserNotificationSocket (options: OverrideCommandOptions = {}) {
+ return io(this.server.url + '/user-notifications', {
+ query: { accessToken: options.token ?? this.server.accessToken }
+ })
+ }
+
+ getLiveNotificationSocket () {
+ return io(this.server.url + '/live-videos')
+ }
+}
+++ /dev/null
-import { io } from 'socket.io-client'
-
-function getUserNotificationSocket (serverUrl: string, accessToken: string) {
- return io(serverUrl + '/user-notifications', {
- query: { accessToken }
- })
-}
-
-function getLiveNotificationSocket (serverUrl: string) {
- return io(serverUrl + '/live-videos')
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getUserNotificationSocket,
- getLiveNotificationSocket
-}
--- /dev/null
+import { HttpStatusCode, ResultList } from '@shared/models'
+import { Account } from '../../models/actors'
+import { AccountVideoRate, VideoRateType } from '../../models/videos'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class AccountsCommand extends AbstractCommand {
+
+ list (options: OverrideCommandOptions & {
+ sort?: string // default -createdAt
+ } = {}) {
+ const { sort = '-createdAt' } = options
+ const path = '/api/v1/accounts'
+
+ return this.getRequestBody<ResultList<Account>>({
+ ...options,
+
+ path,
+ query: { sort },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ get (options: OverrideCommandOptions & {
+ accountName: string
+ }) {
+ const path = '/api/v1/accounts/' + options.accountName
+
+ return this.getRequestBody<Account>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listRatings (options: OverrideCommandOptions & {
+ accountName: string
+ rating?: VideoRateType
+ }) {
+ const { rating, accountName } = options
+ const path = '/api/v1/accounts/' + accountName + '/ratings'
+
+ const query = { rating }
+
+ return this.getRequestBody<ResultList<AccountVideoRate>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import * as request from 'supertest'
-import { expect } from 'chai'
-import { existsSync, readdir } from 'fs-extra'
-import { join } from 'path'
-import { Account } from '../../models/actors'
-import { root } from '../miscs/miscs'
-import { makeGetRequest } from '../requests/requests'
-import { VideoRateType } from '../../models/videos'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/accounts'
-
- return makeGetRequest({
- url,
- query: { sort },
- path,
- statusCodeExpected
- })
-}
-
-function getAccount (url: string, accountName: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/accounts/' + accountName
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected
- })
-}
-
-async function expectAccountFollows (url: string, nameWithDomain: string, followersCount: number, followingCount: number) {
- const res = await getAccountsList(url)
- const account = res.body.data.find((a: Account) => a.name + '@' + a.host === nameWithDomain)
-
- const message = `${nameWithDomain} on ${url}`
- expect(account.followersCount).to.equal(followersCount, message)
- expect(account.followingCount).to.equal(followingCount, message)
-}
-
-async function checkActorFilesWereRemoved (filename: string, serverNumber: number) {
- const testDirectory = 'test' + serverNumber
-
- for (const directory of [ 'avatars' ]) {
- const directoryPath = join(root(), testDirectory, directory)
-
- const directoryExists = existsSync(directoryPath)
- expect(directoryExists).to.be.true
-
- const files = await readdir(directoryPath)
- for (const file of files) {
- expect(file).to.not.contain(filename)
- }
- }
-}
-
-function getAccountRatings (
- url: string,
- accountName: string,
- accessToken: string,
- rating?: VideoRateType,
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/accounts/' + accountName + '/ratings'
-
- const query = rating ? { rating } : {}
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(statusCodeExpected)
- .expect('Content-Type', /json/)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getAccount,
- expectAccountFollows,
- getAccountsList,
- checkActorFilesWereRemoved,
- getAccountRatings
-}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
+
+import { expect } from 'chai'
+import { pathExists, readdir } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { Account, VideoChannel } from '@shared/models'
+import { PeerTubeServer } from '../server'
+
+async function expectChannelsFollows (options: {
+ server: PeerTubeServer
+ handle: string
+ followers: number
+ following: number
+}) {
+ const { server } = options
+ const { data } = await server.channels.list()
+
+ return expectActorFollow({ ...options, data })
+}
+
+async function expectAccountFollows (options: {
+ server: PeerTubeServer
+ handle: string
+ followers: number
+ following: number
+}) {
+ const { server } = options
+ const { data } = await server.accounts.list()
+
+ return expectActorFollow({ ...options, data })
+}
+
+async function checkActorFilesWereRemoved (filename: string, serverNumber: number) {
+ const testDirectory = 'test' + serverNumber
+
+ for (const directory of [ 'avatars' ]) {
+ const directoryPath = join(root(), testDirectory, directory)
+
+ const directoryExists = await pathExists(directoryPath)
+ expect(directoryExists).to.be.true
+
+ const files = await readdir(directoryPath)
+ for (const file of files) {
+ expect(file).to.not.contain(filename)
+ }
+ }
+}
+
+export {
+ expectAccountFollows,
+ expectChannelsFollows,
+ checkActorFilesWereRemoved
+}
+
+// ---------------------------------------------------------------------------
+
+function expectActorFollow (options: {
+ server: PeerTubeServer
+ data: (Account | VideoChannel)[]
+ handle: string
+ followers: number
+ following: number
+}) {
+ const { server, data, handle, followers, following } = options
+
+ const actor = data.find(a => a.name + '@' + a.host === handle)
+ const message = `${handle} on ${server.url}`
+
+ expect(actor, message).to.exist
+ expect(actor.followersCount).to.equal(followers, message)
+ expect(actor.followingCount).to.equal(following, message)
+}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
+
+import { AccountBlock, HttpStatusCode, ResultList, ServerBlock } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+type ListBlocklistOptions = OverrideCommandOptions & {
+ start: number
+ count: number
+ sort: string // default -createdAt
+}
+
+export class BlocklistCommand extends AbstractCommand {
+
+ listMyAccountBlocklist (options: ListBlocklistOptions) {
+ const path = '/api/v1/users/me/blocklist/accounts'
+
+ return this.listBlocklist<AccountBlock>(options, path)
+ }
+
+ listMyServerBlocklist (options: ListBlocklistOptions) {
+ const path = '/api/v1/users/me/blocklist/servers'
+
+ return this.listBlocklist<ServerBlock>(options, path)
+ }
+
+ listServerAccountBlocklist (options: ListBlocklistOptions) {
+ const path = '/api/v1/server/blocklist/accounts'
+
+ return this.listBlocklist<AccountBlock>(options, path)
+ }
+
+ listServerServerBlocklist (options: ListBlocklistOptions) {
+ const path = '/api/v1/server/blocklist/servers'
+
+ return this.listBlocklist<ServerBlock>(options, path)
+ }
+
+ // ---------------------------------------------------------------------------
+
+ addToMyBlocklist (options: OverrideCommandOptions & {
+ account?: string
+ server?: string
+ }) {
+ const { account, server } = options
+
+ const path = account
+ ? '/api/v1/users/me/blocklist/accounts'
+ : '/api/v1/users/me/blocklist/servers'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: {
+ accountName: account,
+ host: server
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ addToServerBlocklist (options: OverrideCommandOptions & {
+ account?: string
+ server?: string
+ }) {
+ const { account, server } = options
+
+ const path = account
+ ? '/api/v1/server/blocklist/accounts'
+ : '/api/v1/server/blocklist/servers'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: {
+ accountName: account,
+ host: server
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ removeFromMyBlocklist (options: OverrideCommandOptions & {
+ account?: string
+ server?: string
+ }) {
+ const { account, server } = options
+
+ const path = account
+ ? '/api/v1/users/me/blocklist/accounts/' + account
+ : '/api/v1/users/me/blocklist/servers/' + server
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ removeFromServerBlocklist (options: OverrideCommandOptions & {
+ account?: string
+ server?: string
+ }) {
+ const { account, server } = options
+
+ const path = account
+ ? '/api/v1/server/blocklist/accounts/' + account
+ : '/api/v1/server/blocklist/servers/' + server
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ private listBlocklist <T> (options: ListBlocklistOptions, path: string) {
+ const { start, count, sort = '-createdAt' } = options
+
+ return this.getRequestBody<ResultList<T>>({
+ ...options,
+
+ path,
+ query: { start, count, sort },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+}
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { makeGetRequest, makeDeleteRequest, makePostBodyRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getAccountBlocklistByAccount (
- url: string,
- token: string,
- start: number,
- count: number,
- sort = '-createdAt',
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/users/me/blocklist/accounts'
-
- return makeGetRequest({
- url,
- token,
- query: { start, count, sort },
- path,
- statusCodeExpected
- })
-}
-
-function addAccountToAccountBlocklist (
- url: string,
- token: string,
- accountToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/me/blocklist/accounts'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: {
- accountName: accountToBlock
- },
- statusCodeExpected
- })
-}
-
-function removeAccountFromAccountBlocklist (
- url: string,
- token: string,
- accountToUnblock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/me/blocklist/accounts/' + accountToUnblock
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function getServerBlocklistByAccount (
- url: string,
- token: string,
- start: number,
- count: number,
- sort = '-createdAt',
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/users/me/blocklist/servers'
-
- return makeGetRequest({
- url,
- token,
- query: { start, count, sort },
- path,
- statusCodeExpected
- })
-}
-
-function addServerToAccountBlocklist (
- url: string,
- token: string,
- serverToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/me/blocklist/servers'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: {
- host: serverToBlock
- },
- statusCodeExpected
- })
-}
-
-function removeServerFromAccountBlocklist (
- url: string,
- token: string,
- serverToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/me/blocklist/servers/' + serverToBlock
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function getAccountBlocklistByServer (
- url: string,
- token: string,
- start: number,
- count: number,
- sort = '-createdAt',
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/server/blocklist/accounts'
-
- return makeGetRequest({
- url,
- token,
- query: { start, count, sort },
- path,
- statusCodeExpected
- })
-}
-
-function addAccountToServerBlocklist (
- url: string,
- token: string,
- accountToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/server/blocklist/accounts'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: {
- accountName: accountToBlock
- },
- statusCodeExpected
- })
-}
-
-function removeAccountFromServerBlocklist (
- url: string,
- token: string,
- accountToUnblock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/server/blocklist/accounts/' + accountToUnblock
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function getServerBlocklistByServer (
- url: string,
- token: string,
- start: number,
- count: number,
- sort = '-createdAt',
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/server/blocklist/servers'
-
- return makeGetRequest({
- url,
- token,
- query: { start, count, sort },
- path,
- statusCodeExpected
- })
-}
-
-function addServerToServerBlocklist (
- url: string,
- token: string,
- serverToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/server/blocklist/servers'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: {
- host: serverToBlock
- },
- statusCodeExpected
- })
-}
-
-function removeServerFromServerBlocklist (
- url: string,
- token: string,
- serverToBlock: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/server/blocklist/servers/' + serverToBlock
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getAccountBlocklistByAccount,
- addAccountToAccountBlocklist,
- removeAccountFromAccountBlocklist,
- getServerBlocklistByAccount,
- addServerToAccountBlocklist,
- removeServerFromAccountBlocklist,
-
- getAccountBlocklistByServer,
- addAccountToServerBlocklist,
- removeAccountFromServerBlocklist,
- getServerBlocklistByServer,
- addServerToServerBlocklist,
- removeServerFromServerBlocklist
-}
--- /dev/null
+export * from './accounts-command'
+export * from './actors'
+export * from './blocklist-command'
+export * from './login'
+export * from './login-command'
+export * from './notifications'
+export * from './notifications-command'
+export * from './subscriptions-command'
+export * from './users-command'
--- /dev/null
+import { HttpStatusCode, PeerTubeProblemDocument } from '@shared/models'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class LoginCommand extends AbstractCommand {
+
+ login (options: OverrideCommandOptions & {
+ client?: { id?: string, secret?: string }
+ user?: { username: string, password?: string }
+ } = {}) {
+ const { client = this.server.store.client, user = this.server.store.user } = options
+ const path = '/api/v1/users/token'
+
+ const body = {
+ client_id: client.id,
+ client_secret: client.secret,
+ username: user.username,
+ password: user.password ?? 'password',
+ response_type: 'code',
+ grant_type: 'password',
+ scope: 'upload'
+ }
+
+ return unwrapBody<{ access_token: string, refresh_token: string } & PeerTubeProblemDocument>(this.postBodyRequest({
+ ...options,
+
+ path,
+ requestType: 'form',
+ fields: body,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ getAccessToken (arg1?: { username: string, password?: string }): Promise<string>
+ getAccessToken (arg1: string, password?: string): Promise<string>
+ async getAccessToken (arg1?: { username: string, password?: string } | string, password?: string) {
+ let user: { username: string, password?: string }
+
+ if (!arg1) user = this.server.store.user
+ else if (typeof arg1 === 'object') user = arg1
+ else user = { username: arg1, password }
+
+ try {
+ const body = await this.login({ user })
+
+ return body.access_token
+ } catch (err) {
+ throw new Error(`Cannot authenticate. Please check your username/password. (${err})`)
+ }
+ }
+
+ loginUsingExternalToken (options: OverrideCommandOptions & {
+ username: string
+ externalAuthToken: string
+ }) {
+ const { username, externalAuthToken } = options
+ const path = '/api/v1/users/token'
+
+ const body = {
+ client_id: this.server.store.client.id,
+ client_secret: this.server.store.client.secret,
+ username: username,
+ response_type: 'code',
+ grant_type: 'password',
+ scope: 'upload',
+ externalAuthToken
+ }
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ requestType: 'form',
+ fields: body,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ logout (options: OverrideCommandOptions & {
+ token: string
+ }) {
+ const path = '/api/v1/users/revoke-token'
+
+ return unwrapBody<{ redirectUrl: string }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ requestType: 'form',
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ refreshToken (options: OverrideCommandOptions & {
+ refreshToken: string
+ }) {
+ const path = '/api/v1/users/token'
+
+ const body = {
+ client_id: this.server.store.client.id,
+ client_secret: this.server.store.client.secret,
+ refresh_token: options.refreshToken,
+ response_type: 'code',
+ grant_type: 'refresh_token'
+ }
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ requestType: 'form',
+ fields: body,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getClient (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/oauth-clients/local'
+
+ return this.getRequestBody<{ client_id: string, client_secret: string }>({
+ ...options,
+
+ path,
+ host: this.server.host,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
-import * as request from 'supertest'
+import { PeerTubeServer } from '../server/server'
-import { ServerInfo } from '../server/servers'
-import { getClient } from '../server/clients'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-type Client = { id: string, secret: string }
-type User = { username: string, password: string }
-type Server = { url: string, client: Client, user: User }
-
-function login (url: string, client: Client, user: User, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/token'
-
- const body = {
- client_id: client.id,
- client_secret: client.secret,
- username: user.username,
- password: user.password,
- response_type: 'code',
- grant_type: 'password',
- scope: 'upload'
- }
-
- return request(url)
- .post(path)
- .type('form')
- .send(body)
- .expect(expectedStatus)
-}
-
-function logout (url: string, token: string, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/revoke-token'
-
- return request(url)
- .post(path)
- .set('Authorization', 'Bearer ' + token)
- .type('form')
- .expect(expectedStatus)
-}
-
-async function serverLogin (server: Server) {
- const res = await login(server.url, server.client, server.user, HttpStatusCode.OK_200)
-
- return res.body.access_token as string
-}
-
-function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/token'
-
- const body = {
- client_id: server.client.id,
- client_secret: server.client.secret,
- refresh_token: refreshToken,
- response_type: 'code',
- grant_type: 'refresh_token'
- }
-
- return request(server.url)
- .post(path)
- .type('form')
- .send(body)
- .expect(expectedStatus)
-}
-
-async function userLogin (server: Server, user: User, expectedStatus = HttpStatusCode.OK_200) {
- const res = await login(server.url, server.client, user, expectedStatus)
-
- return res.body.access_token as string
-}
-
-async function getAccessToken (url: string, username: string, password: string) {
- const resClient = await getClient(url)
- const client = {
- id: resClient.body.client_id,
- secret: resClient.body.client_secret
- }
-
- const user = { username, password }
-
- try {
- const res = await login(url, client, user)
- return res.body.access_token
- } catch (err) {
- throw new Error('Cannot authenticate. Please check your username/password.')
- }
-}
-
-function setAccessTokensToServers (servers: ServerInfo[]) {
+function setAccessTokensToServers (servers: PeerTubeServer[]) {
const tasks: Promise<any>[] = []
for (const server of servers) {
- const p = serverLogin(server).then(t => { server.accessToken = t })
+ const p = server.login.getAccessToken()
+ .then(t => { server.accessToken = t })
tasks.push(p)
}
return Promise.all(tasks)
}
-function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/token'
-
- const body = {
- client_id: server.client.id,
- client_secret: server.client.secret,
- username: username,
- response_type: 'code',
- grant_type: 'password',
- scope: 'upload',
- externalAuthToken
- }
-
- return request(server.url)
- .post(path)
- .type('form')
- .send(body)
- .expect(expectedStatus)
-}
-
// ---------------------------------------------------------------------------
export {
- login,
- logout,
- serverLogin,
- refreshToken,
- userLogin,
- getAccessToken,
- setAccessTokensToServers,
- Server,
- Client,
- User,
- loginUsingExternalToken
+ setAccessTokensToServers
}
--- /dev/null
+import { HttpStatusCode, ResultList } from '@shared/models'
+import { UserNotification, UserNotificationSetting } from '../../models/users'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class NotificationsCommand extends AbstractCommand {
+
+ updateMySettings (options: OverrideCommandOptions & {
+ settings: UserNotificationSetting
+ }) {
+ const path = '/api/v1/users/me/notification-settings'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: options.settings,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ unread?: boolean
+ sort?: string
+ }) {
+ const { start, count, unread, sort = '-createdAt' } = options
+ const path = '/api/v1/users/me/notifications'
+
+ return this.getRequestBody<ResultList<UserNotification>>({
+ ...options,
+
+ path,
+ query: {
+ start,
+ count,
+ sort,
+ unread
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ markAsRead (options: OverrideCommandOptions & {
+ ids: number[]
+ }) {
+ const { ids } = options
+ const path = '/api/v1/users/me/notifications/read'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { ids },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ markAsReadAll (options: OverrideCommandOptions) {
+ const path = '/api/v1/users/me/notifications/read-all'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ async getLastest (options: OverrideCommandOptions = {}) {
+ const { total, data } = await this.list({
+ ...options,
+ start: 0,
+ count: 1,
+ sort: '-createdAt'
+ })
+
+ if (total === 0) return undefined
+
+ return data[0]
+ }
+}
import { expect } from 'chai'
import { inspect } from 'util'
import { AbuseState, PluginType } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
import { UserNotification, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '../../models/users'
-import { MockSmtpServer } from '../miscs/email'
-import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
+import { MockSmtpServer } from '../mock-servers/mock-email'
+import { PeerTubeServer } from '../server'
import { doubleFollow } from '../server/follows'
-import { flushAndRunMultipleServers, ServerInfo } from '../server/servers'
-import { getUserNotificationSocket } from '../socket/socket-io'
-import { setAccessTokensToServers, userLogin } from './login'
-import { createUser, getMyUserInformation } from './users'
-
-function updateMyNotificationSettings (
- url: string,
- token: string,
- settings: UserNotificationSetting,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/me/notification-settings'
-
- return makePutBodyRequest({
- url,
- path,
- token,
- fields: settings,
- statusCodeExpected
- })
-}
-
-async function getUserNotifications (
- url: string,
- token: string,
- start: number,
- count: number,
- unread?: boolean,
- sort = '-createdAt',
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/users/me/notifications'
-
- return makeGetRequest({
- url,
- path,
- token,
- query: {
- start,
- count,
- sort,
- unread
- },
- statusCodeExpected
- })
-}
-
-function markAsReadNotifications (url: string, token: string, ids: number[], statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/me/notifications/read'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: { ids },
- statusCodeExpected
- })
-}
-
-function markAsReadAllNotifications (url: string, token: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/me/notifications/read-all'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-async function getLastNotification (serverUrl: string, accessToken: string) {
- const res = await getUserNotifications(serverUrl, accessToken, 0, 1, undefined, '-createdAt')
-
- if (res.body.total === 0) return undefined
-
- return res.body.data[0] as UserNotification
-}
+import { createMultipleServers } from '../server/servers'
+import { setAccessTokensToServers } from './login'
type CheckerBaseParams = {
- server: ServerInfo
+ server: PeerTubeServer
emails: any[]
socketNotifications: UserNotification[]
token: string
type CheckerType = 'presence' | 'absence'
-async function checkNotification (
- base: CheckerBaseParams,
- notificationChecker: (notification: UserNotification, type: CheckerType) => void,
- emailNotificationFinder: (email: object) => boolean,
- checkType: CheckerType
-) {
- const check = base.check || { web: true, mail: true }
-
- if (check.web) {
- const notification = await getLastNotification(base.server.url, base.token)
-
- if (notification || checkType !== 'absence') {
- notificationChecker(notification, checkType)
- }
-
- const socketNotification = base.socketNotifications.find(n => {
- try {
- notificationChecker(n, 'presence')
- return true
- } catch {
- return false
- }
- })
-
- if (checkType === 'presence') {
- const obj = inspect(base.socketNotifications, { depth: 5 })
- expect(socketNotification, 'The socket notification is absent when it should be present. ' + obj).to.not.be.undefined
- } else {
- const obj = inspect(socketNotification, { depth: 5 })
- expect(socketNotification, 'The socket notification is present when it should not be present. ' + obj).to.be.undefined
- }
- }
-
- if (check.mail) {
- // Last email
- const email = base.emails
- .slice()
- .reverse()
- .find(e => emailNotificationFinder(e))
-
- if (checkType === 'presence') {
- const emails = base.emails.map(e => e.text)
- expect(email, 'The email is absent when is should be present. ' + inspect(emails)).to.not.be.undefined
- } else {
- expect(email, 'The email is present when is should not be present. ' + inspect(email)).to.be.undefined
- }
- }
-}
-
-function checkVideo (video: any, videoName?: string, videoUUID?: string) {
- if (videoName) {
- expect(video.name).to.be.a('string')
- expect(video.name).to.not.be.empty
- expect(video.name).to.equal(videoName)
- }
-
- if (videoUUID) {
- expect(video.uuid).to.be.a('string')
- expect(video.uuid).to.not.be.empty
- expect(video.uuid).to.equal(videoUUID)
+function getAllNotificationsSettings (): UserNotificationSetting {
+ return {
+ newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
+ newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
}
-
- expect(video.id).to.be.a('number')
}
-function checkActor (actor: any) {
- expect(actor.displayName).to.be.a('string')
- expect(actor.displayName).to.not.be.empty
- expect(actor.host).to.not.be.undefined
-}
-
-function checkComment (comment: any, commentId: number, threadId: number) {
- expect(comment.id).to.equal(commentId)
- expect(comment.threadId).to.equal(threadId)
-}
-
-async function checkNewVideoFromSubscription (base: CheckerBaseParams, videoName: string, videoUUID: string, type: CheckerType) {
+async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+}) {
+ const { videoName, shortUUID } = options
const notificationType = UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
- checkVideo(notification.video, videoName, videoUUID)
+ checkVideo(notification.video, videoName, shortUUID)
checkActor(notification.video.channel)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
function emailNotificationFinder (email: object) {
const text = email['text']
- return text.indexOf(videoUUID) !== -1 && text.indexOf('Your subscription') !== -1
+ return text.indexOf(shortUUID) !== -1 && text.indexOf('Your subscription') !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkVideoIsPublished (base: CheckerBaseParams, videoName: string, videoUUID: string, type: CheckerType) {
+async function checkVideoIsPublished (options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ checkType: CheckerType
+}) {
+ const { videoName, shortUUID } = options
const notificationType = UserNotificationType.MY_VIDEO_PUBLISHED
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
- checkVideo(notification.video, videoName, videoUUID)
+ checkVideo(notification.video, videoName, shortUUID)
checkActor(notification.video.channel)
} else {
expect(notification.video).to.satisfy(v => v === undefined || v.name !== videoName)
function emailNotificationFinder (email: object) {
const text: string = email['text']
- return text.includes(videoUUID) && text.includes('Your video')
+ return text.includes(shortUUID) && text.includes('Your video')
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkMyVideoImportIsFinished (
- base: CheckerBaseParams,
- videoName: string,
- videoUUID: string,
- url: string,
- success: boolean,
- type: CheckerType
-) {
+async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
+ videoName: string
+ shortUUID: string
+ url: string
+ success: boolean
+ checkType: CheckerType
+}) {
+ const { videoName, shortUUID, url, success } = options
+
const notificationType = success ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS : UserNotificationType.MY_VIDEO_IMPORT_ERROR
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.videoImport.targetUrl).to.equal(url)
- if (success) checkVideo(notification.videoImport.video, videoName, videoUUID)
+ if (success) checkVideo(notification.videoImport.video, videoName, shortUUID)
} else {
expect(notification.videoImport).to.satisfy(i => i === undefined || i.targetUrl !== url)
}
return text.includes(url) && text.includes(toFind)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkUserRegistered (base: CheckerBaseParams, username: string, type: CheckerType) {
+async function checkUserRegistered (options: CheckerBaseParams & {
+ username: string
+ checkType: CheckerType
+}) {
+ const { username } = options
const notificationType = UserNotificationType.NEW_USER_REGISTRATION
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes(' registered.') && text.includes(username)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewActorFollow (
- base: CheckerBaseParams,
- followType: 'channel' | 'account',
- followerName: string,
- followerDisplayName: string,
- followingDisplayName: string,
- type: CheckerType
-) {
+async function checkNewActorFollow (options: CheckerBaseParams & {
+ followType: 'channel' | 'account'
+ followerName: string
+ followerDisplayName: string
+ followingDisplayName: string
+ checkType: CheckerType
+}) {
+ const { followType, followerName, followerDisplayName, followingDisplayName } = options
const notificationType = UserNotificationType.NEW_FOLLOW
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes(followType) && text.includes(followingDisplayName) && text.includes(followerDisplayName)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewInstanceFollower (base: CheckerBaseParams, followerHost: string, type: CheckerType) {
+async function checkNewInstanceFollower (options: CheckerBaseParams & {
+ followerHost: string
+ checkType: CheckerType
+}) {
+ const { followerHost } = options
const notificationType = UserNotificationType.NEW_INSTANCE_FOLLOWER
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes('instance has a new follower') && text.includes(followerHost)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkAutoInstanceFollowing (base: CheckerBaseParams, followerHost: string, followingHost: string, type: CheckerType) {
+async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
+ followerHost: string
+ followingHost: string
+ checkType: CheckerType
+}) {
+ const { followerHost, followingHost } = options
const notificationType = UserNotificationType.AUTO_INSTANCE_FOLLOWING
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes(' automatically followed a new instance') && text.includes(followingHost)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkCommentMention (
- base: CheckerBaseParams,
- uuid: string,
- commentId: number,
- threadId: number,
- byAccountDisplayName: string,
- type: CheckerType
-) {
+async function checkCommentMention (options: CheckerBaseParams & {
+ shortUUID: string
+ commentId: number
+ threadId: number
+ byAccountDisplayName: string
+ checkType: CheckerType
+}) {
+ const { shortUUID, commentId, threadId, byAccountDisplayName } = options
const notificationType = UserNotificationType.COMMENT_MENTION
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
checkActor(notification.comment.account)
expect(notification.comment.account.displayName).to.equal(byAccountDisplayName)
- checkVideo(notification.comment.video, undefined, uuid)
+ checkVideo(notification.comment.video, undefined, shortUUID)
} else {
expect(notification).to.satisfy(n => n.type !== notificationType || n.comment.id !== commentId)
}
function emailNotificationFinder (email: object) {
const text: string = email['text']
- return text.includes(' mentioned ') && text.includes(uuid) && text.includes(byAccountDisplayName)
+ return text.includes(' mentioned ') && text.includes(shortUUID) && text.includes(byAccountDisplayName)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
let lastEmailCount = 0
-async function checkNewCommentOnMyVideo (base: CheckerBaseParams, uuid: string, commentId: number, threadId: number, type: CheckerType) {
+async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
+ shortUUID: string
+ commentId: number
+ threadId: number
+ checkType: CheckerType
+}) {
+ const { server, shortUUID, commentId, threadId, checkType, emails } = options
const notificationType = UserNotificationType.NEW_COMMENT_ON_MY_VIDEO
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
checkComment(notification.comment, commentId, threadId)
checkActor(notification.comment.account)
- checkVideo(notification.comment.video, undefined, uuid)
+ checkVideo(notification.comment.video, undefined, shortUUID)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
return n === undefined || n.comment === undefined || n.comment.id !== commentId
}
}
- const commentUrl = `http://localhost:${base.server.port}/w/${uuid};threadId=${threadId}`
+ const commentUrl = `http://localhost:${server.port}/w/${shortUUID};threadId=${threadId}`
function emailNotificationFinder (email: object) {
return email['text'].indexOf(commentUrl) !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
- if (type === 'presence') {
+ if (checkType === 'presence') {
// We cannot detect email duplicates, so check we received another email
- expect(base.emails).to.have.length.above(lastEmailCount)
- lastEmailCount = base.emails.length
+ expect(emails).to.have.length.above(lastEmailCount)
+ lastEmailCount = emails.length
}
}
-async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
+async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+}) {
+ const { shortUUID, videoName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.abuse.id).to.be.a('number')
- checkVideo(notification.abuse.video, videoName, videoUUID)
+ checkVideo(notification.abuse.video, videoName, shortUUID)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.video.uuid !== videoUUID
+ return n === undefined || n.abuse === undefined || n.abuse.video.shortUUID !== shortUUID
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
- return text.indexOf(videoUUID) !== -1 && text.indexOf('abuse') !== -1
+ return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewAbuseMessage (base: CheckerBaseParams, abuseId: number, message: string, toEmail: string, type: CheckerType) {
+async function checkNewAbuseMessage (options: CheckerBaseParams & {
+ abuseId: number
+ message: string
+ toEmail: string
+ checkType: CheckerType
+}) {
+ const { abuseId, message, toEmail } = options
const notificationType = UserNotificationType.ABUSE_NEW_MESSAGE
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.indexOf(message) !== -1 && to.length !== 0
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkAbuseStateChange (base: CheckerBaseParams, abuseId: number, state: AbuseState, type: CheckerType) {
+async function checkAbuseStateChange (options: CheckerBaseParams & {
+ abuseId: number
+ state: AbuseState
+ checkType: CheckerType
+}) {
+ const { abuseId, state } = options
const notificationType = UserNotificationType.ABUSE_STATE_CHANGE
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.indexOf(contains) !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewCommentAbuseForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
+async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+}) {
+ const { shortUUID, videoName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.abuse.id).to.be.a('number')
- checkVideo(notification.abuse.comment.video, videoName, videoUUID)
+ checkVideo(notification.abuse.comment.video, videoName, shortUUID)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.comment.video.uuid !== videoUUID
+ return n === undefined || n.abuse === undefined || n.abuse.comment.video.shortUUID !== shortUUID
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
- return text.indexOf(videoUUID) !== -1 && text.indexOf('abuse') !== -1
+ return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewAccountAbuseForModerators (base: CheckerBaseParams, displayName: string, type: CheckerType) {
+async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
+ displayName: string
+ checkType: CheckerType
+}) {
+ const { displayName } = options
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.indexOf(displayName) !== -1 && text.indexOf('abuse') !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkVideoAutoBlacklistForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
+async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
+ checkType: CheckerType
+}) {
+ const { shortUUID, videoName } = options
const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.videoBlacklist.video.id).to.be.a('number')
- checkVideo(notification.videoBlacklist.video, videoName, videoUUID)
+ checkVideo(notification.videoBlacklist.video, videoName, shortUUID)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.video === undefined || n.video.uuid !== videoUUID
+ return n === undefined || n.video === undefined || n.video.shortUUID !== shortUUID
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
- return text.indexOf(videoUUID) !== -1 && email['text'].indexOf('video-auto-blacklist/list') !== -1
+ return text.indexOf(shortUUID) !== -1 && email['text'].indexOf('video-auto-blacklist/list') !== -1
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewBlacklistOnMyVideo (
- base: CheckerBaseParams,
- videoUUID: string,
- videoName: string,
+async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
+ shortUUID: string
+ videoName: string
blacklistType: 'blacklist' | 'unblacklist'
-) {
+}) {
+ const { videoName, shortUUID, blacklistType } = options
const notificationType = blacklistType === 'blacklist'
? UserNotificationType.BLACKLIST_ON_MY_VIDEO
: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO
const video = blacklistType === 'blacklist' ? notification.videoBlacklist.video : notification.video
- checkVideo(video, videoName, videoUUID)
+ checkVideo(video, videoName, shortUUID)
}
function emailNotificationFinder (email: object) {
const text = email['text']
- return text.indexOf(videoUUID) !== -1 && text.indexOf(' ' + blacklistType) !== -1
+ const blacklistText = blacklistType === 'blacklist'
+ ? 'blacklisted'
+ : 'unblacklisted'
+
+ return text.includes(shortUUID) && text.includes(blacklistText)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, 'presence')
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder, checkType: 'presence' })
}
-async function checkNewPeerTubeVersion (base: CheckerBaseParams, latestVersion: string, type: CheckerType) {
+async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
+ latestVersion: string
+ checkType: CheckerType
+}) {
+ const { latestVersion } = options
const notificationType = UserNotificationType.NEW_PEERTUBE_VERSION
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes(latestVersion)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
-async function checkNewPluginVersion (base: CheckerBaseParams, pluginType: PluginType, pluginName: string, type: CheckerType) {
+async function checkNewPluginVersion (options: CheckerBaseParams & {
+ pluginType: PluginType
+ pluginName: string
+ checkType: CheckerType
+}) {
+ const { pluginName, pluginType } = options
const notificationType = UserNotificationType.NEW_PLUGIN_VERSION
- function notificationChecker (notification: UserNotification, type: CheckerType) {
- if (type === 'presence') {
+ function notificationChecker (notification: UserNotification, checkType: CheckerType) {
+ if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
return text.includes(pluginName)
}
- await checkNotification(base, notificationChecker, emailNotificationFinder, type)
-}
-
-function getAllNotificationsSettings (): UserNotificationSetting {
- return {
- newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
- }
+ await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) {
limit: 20
}
}
- const servers = await flushAndRunMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
+ const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
}
- const user = {
- username: 'user_1',
- password: 'super password'
- }
- await createUser({
- url: servers[0].url,
- accessToken: servers[0].accessToken,
- username: user.username,
- password: user.password,
- videoQuota: 10 * 1000 * 1000
- })
- const userAccessToken = await userLogin(servers[0], user)
+ const user = { username: 'user_1', password: 'super password' }
+ await servers[0].users.create({ ...user, videoQuota: 10 * 1000 * 1000 })
+ const userAccessToken = await servers[0].login.getAccessToken(user)
- await updateMyNotificationSettings(servers[0].url, userAccessToken, getAllNotificationsSettings())
- await updateMyNotificationSettings(servers[0].url, servers[0].accessToken, getAllNotificationsSettings())
+ await servers[0].notifications.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
+ await servers[0].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
if (serversCount > 1) {
- await updateMyNotificationSettings(servers[1].url, servers[1].accessToken, getAllNotificationsSettings())
+ await servers[1].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
}
{
- const socket = getUserNotificationSocket(servers[0].url, userAccessToken)
+ const socket = servers[0].socketIO.getUserNotificationSocket({ token: userAccessToken })
socket.on('new-notification', n => userNotifications.push(n))
}
{
- const socket = getUserNotificationSocket(servers[0].url, servers[0].accessToken)
+ const socket = servers[0].socketIO.getUserNotificationSocket()
socket.on('new-notification', n => adminNotifications.push(n))
}
if (serversCount > 1) {
- const socket = getUserNotificationSocket(servers[1].url, servers[1].accessToken)
+ const socket = servers[1].socketIO.getUserNotificationSocket()
socket.on('new-notification', n => adminNotificationsServer2.push(n))
}
- const resChannel = await getMyUserInformation(servers[0].url, servers[0].accessToken)
- const channelId = resChannel.body.videoChannels[0].id
+ const { videoChannels } = await servers[0].users.getMyInfo()
+ const channelId = videoChannels[0].id
return {
userNotifications,
// ---------------------------------------------------------------------------
export {
+ getAllNotificationsSettings,
+
CheckerBaseParams,
CheckerType,
- getAllNotificationsSettings,
- checkNotification,
- markAsReadAllNotifications,
checkMyVideoImportIsFinished,
checkUserRegistered,
checkAutoInstanceFollowing,
checkNewCommentOnMyVideo,
checkNewBlacklistOnMyVideo,
checkCommentMention,
- updateMyNotificationSettings,
checkNewVideoAbuseForModerators,
checkVideoAutoBlacklistForModerators,
checkNewAbuseMessage,
checkAbuseStateChange,
- getUserNotifications,
- markAsReadNotifications,
- getLastNotification,
checkNewInstanceFollower,
prepareNotificationsTest,
checkNewCommentAbuseForModerators,
checkNewPeerTubeVersion,
checkNewPluginVersion
}
+
+// ---------------------------------------------------------------------------
+
+async function checkNotification (options: CheckerBaseParams & {
+ notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
+ emailNotificationFinder: (email: object) => boolean
+ checkType: CheckerType
+}) {
+ const { server, token, checkType, notificationChecker, emailNotificationFinder, socketNotifications, emails } = options
+
+ const check = options.check || { web: true, mail: true }
+
+ if (check.web) {
+ const notification = await server.notifications.getLastest({ token: token })
+
+ if (notification || checkType !== 'absence') {
+ notificationChecker(notification, checkType)
+ }
+
+ const socketNotification = socketNotifications.find(n => {
+ try {
+ notificationChecker(n, 'presence')
+ return true
+ } catch {
+ return false
+ }
+ })
+
+ if (checkType === 'presence') {
+ const obj = inspect(socketNotifications, { depth: 5 })
+ expect(socketNotification, 'The socket notification is absent when it should be present. ' + obj).to.not.be.undefined
+ } else {
+ const obj = inspect(socketNotification, { depth: 5 })
+ expect(socketNotification, 'The socket notification is present when it should not be present. ' + obj).to.be.undefined
+ }
+ }
+
+ if (check.mail) {
+ // Last email
+ const email = emails
+ .slice()
+ .reverse()
+ .find(e => emailNotificationFinder(e))
+
+ if (checkType === 'presence') {
+ const texts = emails.map(e => e.text)
+ expect(email, 'The email is absent when is should be present. ' + inspect(texts)).to.not.be.undefined
+ } else {
+ expect(email, 'The email is present when is should not be present. ' + inspect(email)).to.be.undefined
+ }
+ }
+}
+
+function checkVideo (video: any, videoName?: string, shortUUID?: string) {
+ if (videoName) {
+ expect(video.name).to.be.a('string')
+ expect(video.name).to.not.be.empty
+ expect(video.name).to.equal(videoName)
+ }
+
+ if (shortUUID) {
+ expect(video.shortUUID).to.be.a('string')
+ expect(video.shortUUID).to.not.be.empty
+ expect(video.shortUUID).to.equal(shortUUID)
+ }
+
+ expect(video.id).to.be.a('number')
+}
+
+function checkActor (actor: any) {
+ expect(actor.displayName).to.be.a('string')
+ expect(actor.displayName).to.not.be.empty
+ expect(actor.host).to.not.be.undefined
+}
+
+function checkComment (comment: any, commentId: number, threadId: number) {
+ expect(comment.id).to.equal(commentId)
+ expect(comment.threadId).to.equal(threadId)
+}
--- /dev/null
+import { HttpStatusCode, ResultList, Video, VideoChannel } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class SubscriptionsCommand extends AbstractCommand {
+
+ add (options: OverrideCommandOptions & {
+ targetUri: string
+ }) {
+ const path = '/api/v1/users/me/subscriptions'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { uri: options.targetUri },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ sort?: string // default -createdAt
+ search?: string
+ } = {}) {
+ const { sort = '-createdAt', search } = options
+ const path = '/api/v1/users/me/subscriptions'
+
+ return this.getRequestBody<ResultList<VideoChannel>>({
+ ...options,
+
+ path,
+ query: {
+ sort,
+ search
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listVideos (options: OverrideCommandOptions & {
+ sort?: string // default -createdAt
+ } = {}) {
+ const { sort = '-createdAt' } = options
+ const path = '/api/v1/users/me/subscriptions/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: { sort },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ get (options: OverrideCommandOptions & {
+ uri: string
+ }) {
+ const path = '/api/v1/users/me/subscriptions/' + options.uri
+
+ return this.getRequestBody<VideoChannel>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ remove (options: OverrideCommandOptions & {
+ uri: string
+ }) {
+ const path = '/api/v1/users/me/subscriptions/' + options.uri
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ exist (options: OverrideCommandOptions & {
+ uris: string[]
+ }) {
+ const path = '/api/v1/users/me/subscriptions/exist'
+
+ return this.getRequestBody<{ [id: string ]: boolean }>({
+ ...options,
+
+ path,
+ query: { 'uris[]': options.uris },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import { makeDeleteRequest, makeGetRequest, makePostBodyRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function addUserSubscription (url: string, token: string, targetUri: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/me/subscriptions'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- statusCodeExpected,
- fields: { uri: targetUri }
- })
-}
-
-function listUserSubscriptions (parameters: {
- url: string
- token: string
- sort?: string
- search?: string
- statusCodeExpected?: number
-}) {
- const { url, token, sort = '-createdAt', search, statusCodeExpected = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/users/me/subscriptions'
-
- return makeGetRequest({
- url,
- path,
- token,
- statusCodeExpected,
- query: {
- sort,
- search
- }
- })
-}
-
-function listUserSubscriptionVideos (url: string, token: string, sort = '-createdAt', statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me/subscriptions/videos'
-
- return makeGetRequest({
- url,
- path,
- token,
- statusCodeExpected,
- query: { sort }
- })
-}
-
-function getUserSubscription (url: string, token: string, uri: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me/subscriptions/' + uri
-
- return makeGetRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function removeUserSubscription (url: string, token: string, uri: string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/me/subscriptions/' + uri
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function areSubscriptionsExist (url: string, token: string, uris: string[], statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me/subscriptions/exist'
-
- return makeGetRequest({
- url,
- path,
- query: { 'uris[]': uris },
- token,
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- areSubscriptionsExist,
- addUserSubscription,
- listUserSubscriptions,
- getUserSubscription,
- listUserSubscriptionVideos,
- removeUserSubscription
-}
--- /dev/null
+import { omit } from 'lodash'
+import { pick } from '@shared/core-utils'
+import {
+ HttpStatusCode,
+ MyUser,
+ ResultList,
+ User,
+ UserAdminFlag,
+ UserCreateResult,
+ UserRole,
+ UserUpdate,
+ UserUpdateMe,
+ UserVideoQuota,
+ UserVideoRate
+} from '@shared/models'
+import { ScopedToken } from '@shared/models/users/user-scoped-token'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class UsersCommand extends AbstractCommand {
+
+ askResetPassword (options: OverrideCommandOptions & {
+ email: string
+ }) {
+ const { email } = options
+ const path = '/api/v1/users/ask-reset-password'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { email },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ resetPassword (options: OverrideCommandOptions & {
+ userId: number
+ verificationString: string
+ password: string
+ }) {
+ const { userId, verificationString, password } = options
+ const path = '/api/v1/users/' + userId + '/reset-password'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { password, verificationString },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ askSendVerifyEmail (options: OverrideCommandOptions & {
+ email: string
+ }) {
+ const { email } = options
+ const path = '/api/v1/users/ask-send-verify-email'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { email },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ verifyEmail (options: OverrideCommandOptions & {
+ userId: number
+ verificationString: string
+ isPendingEmail?: boolean // default false
+ }) {
+ const { userId, verificationString, isPendingEmail = false } = options
+ const path = '/api/v1/users/' + userId + '/verify-email'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: {
+ verificationString,
+ isPendingEmail
+ },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ banUser (options: OverrideCommandOptions & {
+ userId: number
+ reason?: string
+ }) {
+ const { userId, reason } = options
+ const path = '/api/v1/users' + '/' + userId + '/block'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { reason },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ unbanUser (options: OverrideCommandOptions & {
+ userId: number
+ }) {
+ const { userId } = options
+ const path = '/api/v1/users' + '/' + userId + '/unblock'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ getMyScopedTokens (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/users/scoped-tokens'
+
+ return this.getRequestBody<ScopedToken>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ renewMyScopedTokens (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/users/scoped-tokens'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ create (options: OverrideCommandOptions & {
+ username: string
+ password?: string
+ videoQuota?: number
+ videoQuotaDaily?: number
+ role?: UserRole
+ adminFlags?: UserAdminFlag
+ }) {
+ const {
+ username,
+ adminFlags,
+ password = 'password',
+ videoQuota = 42000000,
+ videoQuotaDaily = -1,
+ role = UserRole.USER
+ } = options
+
+ const path = '/api/v1/users'
+
+ return unwrapBody<{ user: UserCreateResult }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: {
+ username,
+ password,
+ role,
+ adminFlags,
+ email: username + '@example.com',
+ videoQuota,
+ videoQuotaDaily
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })).then(res => res.user)
+ }
+
+ async generate (username: string) {
+ const password = 'password'
+ const user = await this.create({ username, password })
+
+ const token = await this.server.login.getAccessToken({ username, password })
+
+ const me = await this.getMyInfo({ token })
+
+ return {
+ token,
+ userId: user.id,
+ userChannelId: me.videoChannels[0].id
+ }
+ }
+
+ async generateUserAndToken (username: string) {
+ const password = 'password'
+ await this.create({ username, password })
+
+ return this.server.login.getAccessToken({ username, password })
+ }
+
+ register (options: OverrideCommandOptions & {
+ username: string
+ password?: string
+ displayName?: string
+ channel?: {
+ name: string
+ displayName: string
+ }
+ }) {
+ const { username, password = 'password', displayName, channel } = options
+ const path = '/api/v1/users/register'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: {
+ username,
+ password,
+ email: username + '@example.com',
+ displayName,
+ channel
+ },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ getMyInfo (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/users/me'
+
+ return this.getRequestBody<MyUser>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getMyQuotaUsed (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/users/me/video-quota-used'
+
+ return this.getRequestBody<UserVideoQuota>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getMyRating (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const { videoId } = options
+ const path = '/api/v1/users/me/videos/' + videoId + '/rating'
+
+ return this.getRequestBody<UserVideoRate>({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ deleteMe (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/users/me'
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ updateMe (options: OverrideCommandOptions & UserUpdateMe) {
+ const path = '/api/v1/users/me'
+
+ const toSend: UserUpdateMe = omit(options, 'url', 'accessToken')
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: toSend,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ updateMyAvatar (options: OverrideCommandOptions & {
+ fixture: string
+ }) {
+ const { fixture } = options
+ const path = '/api/v1/users/me/avatar/pick'
+
+ return this.updateImageRequest({
+ ...options,
+
+ path,
+ fixture,
+ fieldname: 'avatarfile',
+
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ get (options: OverrideCommandOptions & {
+ userId: number
+ withStats?: boolean // default false
+ }) {
+ const { userId, withStats } = options
+ const path = '/api/v1/users/' + userId
+
+ return this.getRequestBody<User>({
+ ...options,
+
+ path,
+ query: { withStats },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ search?: string
+ blocked?: boolean
+ } = {}) {
+ const path = '/api/v1/users'
+
+ return this.getRequestBody<ResultList<User>>({
+ ...options,
+
+ path,
+ query: pick(options, [ 'start', 'count', 'sort', 'search', 'blocked' ]),
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ remove (options: OverrideCommandOptions & {
+ userId: number
+ }) {
+ const { userId } = options
+ const path = '/api/v1/users/' + userId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ update (options: OverrideCommandOptions & {
+ userId: number
+ email?: string
+ emailVerified?: boolean
+ videoQuota?: number
+ videoQuotaDaily?: number
+ password?: string
+ adminFlags?: UserAdminFlag
+ pluginAuth?: string
+ role?: UserRole
+ }) {
+ const path = '/api/v1/users/' + options.userId
+
+ const toSend: UserUpdate = {}
+ if (options.password !== undefined && options.password !== null) toSend.password = options.password
+ if (options.email !== undefined && options.email !== null) toSend.email = options.email
+ if (options.emailVerified !== undefined && options.emailVerified !== null) toSend.emailVerified = options.emailVerified
+ if (options.videoQuota !== undefined && options.videoQuota !== null) toSend.videoQuota = options.videoQuota
+ if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend.videoQuotaDaily = options.videoQuotaDaily
+ if (options.role !== undefined && options.role !== null) toSend.role = options.role
+ if (options.adminFlags !== undefined && options.adminFlags !== null) toSend.adminFlags = options.adminFlags
+ if (options.pluginAuth !== undefined) toSend.pluginAuth = options.pluginAuth
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: toSend,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
+++ /dev/null
-import { omit } from 'lodash'
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { UserUpdateMe } from '../../models/users'
-import { UserAdminFlag } from '../../models/users/user-flag.model'
-import { UserRegister } from '../../models/users/user-register.model'
-import { UserRole } from '../../models/users/user-role'
-import { makeGetRequest, makePostBodyRequest, makePutBodyRequest, updateImageRequest } from '../requests/requests'
-import { ServerInfo } from '../server/servers'
-import { userLogin } from './login'
-
-function createUser (parameters: {
- url: string
- accessToken: string
- username: string
- password: string
- videoQuota?: number
- videoQuotaDaily?: number
- role?: UserRole
- adminFlags?: UserAdminFlag
- specialStatus?: number
-}) {
- const {
- url,
- accessToken,
- username,
- adminFlags,
- password = 'password',
- videoQuota = 1000000,
- videoQuotaDaily = -1,
- role = UserRole.USER,
- specialStatus = HttpStatusCode.OK_200
- } = parameters
-
- const path = '/api/v1/users'
- const body = {
- username,
- password,
- role,
- adminFlags,
- email: username + '@example.com',
- videoQuota,
- videoQuotaDaily
- }
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .send(body)
- .expect(specialStatus)
-}
-
-async function generateUser (server: ServerInfo, username: string) {
- const password = 'my super password'
- const resCreate = await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
-
- const token = await userLogin(server, { username, password })
-
- const resMe = await getMyUserInformation(server.url, token)
-
- return {
- token,
- userId: resCreate.body.user.id,
- userChannelId: resMe.body.videoChannels[0].id
- }
-}
-
-async function generateUserAccessToken (server: ServerInfo, username: string) {
- const password = 'my super password'
- await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
-
- return userLogin(server, { username, password })
-}
-
-function registerUser (url: string, username: string, password: string, specialStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/register'
- const body = {
- username,
- password,
- email: username + '@example.com'
- }
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .send(body)
- .expect(specialStatus)
-}
-
-function registerUserWithChannel (options: {
- url: string
- user: { username: string, password: string, displayName?: string }
- channel: { name: string, displayName: string }
-}) {
- const path = '/api/v1/users/register'
- const body: UserRegister = {
- username: options.user.username,
- password: options.user.password,
- email: options.user.username + '@example.com',
- channel: options.channel
- }
-
- if (options.user.displayName) {
- Object.assign(body, { displayName: options.user.displayName })
- }
-
- return makePostBodyRequest({
- url: options.url,
- path,
- fields: body,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function getMyUserInformation (url: string, accessToken: string, specialStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me'
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(specialStatus)
- .expect('Content-Type', /json/)
-}
-
-function getUserScopedTokens (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/scoped-tokens'
-
- return makeGetRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function renewUserScopedTokens (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/scoped-tokens'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function deleteMe (url: string, accessToken: string, specialStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users/me'
-
- return request(url)
- .delete(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(specialStatus)
-}
-
-function getMyUserVideoQuotaUsed (url: string, accessToken: string, specialStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me/video-quota-used'
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(specialStatus)
- .expect('Content-Type', /json/)
-}
-
-function getUserInformation (url: string, accessToken: string, userId: number, withStats = false) {
- const path = '/api/v1/users/' + userId
-
- return request(url)
- .get(path)
- .query({ withStats })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getMyUserVideoRating (url: string, accessToken: string, videoId: number | string, specialStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/users/me/videos/' + videoId + '/rating'
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(specialStatus)
- .expect('Content-Type', /json/)
-}
-
-function getUsersList (url: string, accessToken: string) {
- const path = '/api/v1/users'
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getUsersListPaginationAndSort (
- url: string,
- accessToken: string,
- start: number,
- count: number,
- sort: string,
- search?: string,
- blocked?: boolean
-) {
- const path = '/api/v1/users'
-
- const query = {
- start,
- count,
- sort,
- search,
- blocked
- }
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function removeUser (url: string, userId: number | string, accessToken: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users'
-
- return request(url)
- .delete(path + '/' + userId)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(expectedStatus)
-}
-
-function blockUser (
- url: string,
- userId: number | string,
- accessToken: string,
- expectedStatus = HttpStatusCode.NO_CONTENT_204,
- reason?: string
-) {
- const path = '/api/v1/users'
- let body: any
- if (reason) body = { reason }
-
- return request(url)
- .post(path + '/' + userId + '/block')
- .send(body)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(expectedStatus)
-}
-
-function unblockUser (url: string, userId: number | string, accessToken: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/users'
-
- return request(url)
- .post(path + '/' + userId + '/unblock')
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(expectedStatus)
-}
-
-function updateMyUser (options: { url: string, accessToken: string, statusCodeExpected?: HttpStatusCode } & UserUpdateMe) {
- const path = '/api/v1/users/me'
-
- const toSend: UserUpdateMe = omit(options, 'url', 'accessToken')
-
- return makePutBodyRequest({
- url: options.url,
- path,
- token: options.accessToken,
- fields: toSend,
- statusCodeExpected: options.statusCodeExpected || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function updateMyAvatar (options: {
- url: string
- accessToken: string
- fixture: string
-}) {
- const path = '/api/v1/users/me/avatar/pick'
-
- return updateImageRequest({ ...options, path, fieldname: 'avatarfile' })
-}
-
-function updateUser (options: {
- url: string
- userId: number
- accessToken: string
- email?: string
- emailVerified?: boolean
- videoQuota?: number
- videoQuotaDaily?: number
- password?: string
- adminFlags?: UserAdminFlag
- pluginAuth?: string
- role?: UserRole
-}) {
- const path = '/api/v1/users/' + options.userId
-
- const toSend = {}
- if (options.password !== undefined && options.password !== null) toSend['password'] = options.password
- if (options.email !== undefined && options.email !== null) toSend['email'] = options.email
- if (options.emailVerified !== undefined && options.emailVerified !== null) toSend['emailVerified'] = options.emailVerified
- if (options.videoQuota !== undefined && options.videoQuota !== null) toSend['videoQuota'] = options.videoQuota
- if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily
- if (options.role !== undefined && options.role !== null) toSend['role'] = options.role
- if (options.adminFlags !== undefined && options.adminFlags !== null) toSend['adminFlags'] = options.adminFlags
- if (options.pluginAuth !== undefined) toSend['pluginAuth'] = options.pluginAuth
-
- return makePutBodyRequest({
- url: options.url,
- path,
- token: options.accessToken,
- fields: toSend,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function askResetPassword (url: string, email: string) {
- const path = '/api/v1/users/ask-reset-password'
-
- return makePostBodyRequest({
- url,
- path,
- fields: { email },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function resetPassword (
- url: string,
- userId: number,
- verificationString: string,
- password: string,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/' + userId + '/reset-password'
-
- return makePostBodyRequest({
- url,
- path,
- fields: { password, verificationString },
- statusCodeExpected
- })
-}
-
-function askSendVerifyEmail (url: string, email: string) {
- const path = '/api/v1/users/ask-send-verify-email'
-
- return makePostBodyRequest({
- url,
- path,
- fields: { email },
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function verifyEmail (
- url: string,
- userId: number,
- verificationString: string,
- isPendingEmail = false,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/users/' + userId + '/verify-email'
-
- return makePostBodyRequest({
- url,
- path,
- fields: {
- verificationString,
- isPendingEmail
- },
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- createUser,
- registerUser,
- getMyUserInformation,
- getMyUserVideoRating,
- deleteMe,
- registerUserWithChannel,
- getMyUserVideoQuotaUsed,
- getUsersList,
- getUsersListPaginationAndSort,
- removeUser,
- updateUser,
- updateMyUser,
- getUserInformation,
- blockUser,
- unblockUser,
- askResetPassword,
- resetPassword,
- renewUserScopedTokens,
- updateMyAvatar,
- generateUser,
- askSendVerifyEmail,
- generateUserAccessToken,
- verifyEmail,
- getUserScopedTokens
-}
--- /dev/null
+
+import { HttpStatusCode, ResultList } from '@shared/models'
+import { VideoBlacklist, VideoBlacklistType } from '../../models/videos'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class BlacklistCommand extends AbstractCommand {
+
+ add (options: OverrideCommandOptions & {
+ videoId: number | string
+ reason?: string
+ unfederate?: boolean
+ }) {
+ const { videoId, reason, unfederate } = options
+ const path = '/api/v1/videos/' + videoId + '/blacklist'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { reason, unfederate },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ update (options: OverrideCommandOptions & {
+ videoId: number | string
+ reason?: string
+ }) {
+ const { videoId, reason } = options
+ const path = '/api/v1/videos/' + videoId + '/blacklist'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: { reason },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ remove (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const { videoId } = options
+ const path = '/api/v1/videos/' + videoId + '/blacklist'
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ sort?: string
+ type?: VideoBlacklistType
+ } = {}) {
+ const { sort, type } = options
+ const path = '/api/v1/videos/blacklist/'
+
+ const query = { sort, type }
+
+ return this.getRequestBody<ResultList<VideoBlacklist>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
--- /dev/null
+import { HttpStatusCode, ResultList, VideoCaption } from '@shared/models'
+import { buildAbsoluteFixturePath } from '../miscs'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class CaptionsCommand extends AbstractCommand {
+
+ add (options: OverrideCommandOptions & {
+ videoId: string | number
+ language: string
+ fixture: string
+ mimeType?: string
+ }) {
+ const { videoId, language, fixture, mimeType } = options
+
+ const path = '/api/v1/videos/' + videoId + '/captions/' + language
+
+ const captionfile = buildAbsoluteFixturePath(fixture)
+ const captionfileAttach = mimeType
+ ? [ captionfile, { contentType: mimeType } ]
+ : captionfile
+
+ return this.putUploadRequest({
+ ...options,
+
+ path,
+ fields: {},
+ attaches: {
+ captionfile: captionfileAttach
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ videoId: string | number
+ }) {
+ const { videoId } = options
+ const path = '/api/v1/videos/' + videoId + '/captions'
+
+ return this.getRequestBody<ResultList<VideoCaption>>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ delete (options: OverrideCommandOptions & {
+ videoId: string | number
+ language: string
+ }) {
+ const { videoId, language } = options
+ const path = '/api/v1/videos/' + videoId + '/captions/' + language
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
--- /dev/null
+import { expect } from 'chai'
+import * as request from 'supertest'
+import { HttpStatusCode } from '@shared/models'
+
+async function testCaptionFile (url: string, captionPath: string, containsString: string) {
+ const res = await request(url)
+ .get(captionPath)
+ .expect(HttpStatusCode.OK_200)
+
+ expect(res.text).to.contain(containsString)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ testCaptionFile
+}
--- /dev/null
+
+import { HttpStatusCode, ResultList, VideoChangeOwnership } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ChangeOwnershipCommand extends AbstractCommand {
+
+ create (options: OverrideCommandOptions & {
+ videoId: number | string
+ username: string
+ }) {
+ const { videoId, username } = options
+ const path = '/api/v1/videos/' + videoId + '/give-ownership'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { username },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/videos/ownership'
+
+ return this.getRequestBody<ResultList<VideoChangeOwnership>>({
+ ...options,
+
+ path,
+ query: { sort: '-createdAt' },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ accept (options: OverrideCommandOptions & {
+ ownershipId: number
+ channelId: number
+ }) {
+ const { ownershipId, channelId } = options
+ const path = '/api/v1/videos/ownership/' + ownershipId + '/accept'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { channelId },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ refuse (options: OverrideCommandOptions & {
+ ownershipId: number
+ }) {
+ const { ownershipId } = options
+ const path = '/api/v1/videos/ownership/' + ownershipId + '/refuse'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
--- /dev/null
+import { pick } from '@shared/core-utils'
+import { HttpStatusCode, ResultList, VideoChannel, VideoChannelCreateResult } from '@shared/models'
+import { VideoChannelCreate } from '../../models/videos/channel/video-channel-create.model'
+import { VideoChannelUpdate } from '../../models/videos/channel/video-channel-update.model'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ChannelsCommand extends AbstractCommand {
+
+ list (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ withStats?: boolean
+ } = {}) {
+ const path = '/api/v1/video-channels'
+
+ return this.getRequestBody<ResultList<VideoChannel>>({
+ ...options,
+
+ path,
+ query: pick(options, [ 'start', 'count', 'sort', 'withStats' ]),
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listByAccount (options: OverrideCommandOptions & {
+ accountName: string
+ start?: number
+ count?: number
+ sort?: string
+ withStats?: boolean
+ search?: string
+ }) {
+ const { accountName, sort = 'createdAt' } = options
+ const path = '/api/v1/accounts/' + accountName + '/video-channels'
+
+ return this.getRequestBody<ResultList<VideoChannel>>({
+ ...options,
+
+ path,
+ query: { sort, ...pick(options, [ 'start', 'count', 'withStats', 'search' ]) },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ async create (options: OverrideCommandOptions & {
+ attributes: VideoChannelCreate
+ }) {
+ const path = '/api/v1/video-channels/'
+
+ // Default attributes
+ const defaultAttributes = {
+ displayName: 'my super video channel',
+ description: 'my super channel description',
+ support: 'my super channel support'
+ }
+ const attributes = { ...defaultAttributes, ...options.attributes }
+
+ const body = await unwrapBody<{ videoChannel: VideoChannelCreateResult }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ return body.videoChannel
+ }
+
+ update (options: OverrideCommandOptions & {
+ channelName: string
+ attributes: VideoChannelUpdate
+ }) {
+ const { channelName, attributes } = options
+ const path = '/api/v1/video-channels/' + channelName
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ delete (options: OverrideCommandOptions & {
+ channelName: string
+ }) {
+ const path = '/api/v1/video-channels/' + options.channelName
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ get (options: OverrideCommandOptions & {
+ channelName: string
+ }) {
+ const path = '/api/v1/video-channels/' + options.channelName
+
+ return this.getRequestBody<VideoChannel>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ updateImage (options: OverrideCommandOptions & {
+ fixture: string
+ channelName: string | number
+ type: 'avatar' | 'banner'
+ }) {
+ const { channelName, fixture, type } = options
+
+ const path = `/api/v1/video-channels/${channelName}/${type}/pick`
+
+ return this.updateImageRequest({
+ ...options,
+
+ path,
+ fixture,
+ fieldname: type + 'file',
+
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ deleteImage (options: OverrideCommandOptions & {
+ channelName: string | number
+ type: 'avatar' | 'banner'
+ }) {
+ const { channelName, type } = options
+
+ const path = `/api/v1/video-channels/${channelName}/${type}`
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
--- /dev/null
+import { PeerTubeServer } from '../server/server'
+
+function setDefaultVideoChannel (servers: PeerTubeServer[]) {
+ const tasks: Promise<any>[] = []
+
+ for (const server of servers) {
+ const p = server.users.getMyInfo()
+ .then(user => { server.store.channel = user.videoChannels[0] })
+
+ tasks.push(p)
+ }
+
+ return Promise.all(tasks)
+}
+
+export {
+ setDefaultVideoChannel
+}
--- /dev/null
+import { pick } from 'lodash'
+import { HttpStatusCode, ResultList, VideoComment, VideoCommentThreads, VideoCommentThreadTree } from '@shared/models'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class CommentsCommand extends AbstractCommand {
+
+ private lastVideoId: number | string
+ private lastThreadId: number
+ private lastReplyId: number
+
+ listForAdmin (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ isLocal?: boolean
+ search?: string
+ searchAccount?: string
+ searchVideo?: string
+ } = {}) {
+ const { sort = '-createdAt' } = options
+ const path = '/api/v1/videos/comments'
+
+ const query = { sort, ...pick(options, [ 'start', 'count', 'isLocal', 'search', 'searchAccount', 'searchVideo' ]) }
+
+ return this.getRequestBody<ResultList<VideoComment>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listThreads (options: OverrideCommandOptions & {
+ videoId: number | string
+ start?: number
+ count?: number
+ sort?: string
+ }) {
+ const { start, count, sort, videoId } = options
+ const path = '/api/v1/videos/' + videoId + '/comment-threads'
+
+ return this.getRequestBody<VideoCommentThreads>({
+ ...options,
+
+ path,
+ query: { start, count, sort },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getThread (options: OverrideCommandOptions & {
+ videoId: number | string
+ threadId: number
+ }) {
+ const { videoId, threadId } = options
+ const path = '/api/v1/videos/' + videoId + '/comment-threads/' + threadId
+
+ return this.getRequestBody<VideoCommentThreadTree>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ async createThread (options: OverrideCommandOptions & {
+ videoId: number | string
+ text: string
+ }) {
+ const { videoId, text } = options
+ const path = '/api/v1/videos/' + videoId + '/comment-threads'
+
+ const body = await unwrapBody<{ comment: VideoComment }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { text },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ this.lastThreadId = body.comment?.id
+ this.lastVideoId = videoId
+
+ return body.comment
+ }
+
+ async addReply (options: OverrideCommandOptions & {
+ videoId: number | string
+ toCommentId: number
+ text: string
+ }) {
+ const { videoId, toCommentId, text } = options
+ const path = '/api/v1/videos/' + videoId + '/comments/' + toCommentId
+
+ const body = await unwrapBody<{ comment: VideoComment }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { text },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ this.lastReplyId = body.comment?.id
+
+ return body.comment
+ }
+
+ async addReplyToLastReply (options: OverrideCommandOptions & {
+ text: string
+ }) {
+ return this.addReply({ ...options, videoId: this.lastVideoId, toCommentId: this.lastReplyId })
+ }
+
+ async addReplyToLastThread (options: OverrideCommandOptions & {
+ text: string
+ }) {
+ return this.addReply({ ...options, videoId: this.lastVideoId, toCommentId: this.lastThreadId })
+ }
+
+ async findCommentId (options: OverrideCommandOptions & {
+ videoId: number | string
+ text: string
+ }) {
+ const { videoId, text } = options
+ const { data } = await this.listThreads({ videoId, count: 25, sort: '-createdAt' })
+
+ return data.find(c => c.text === text).id
+ }
+
+ delete (options: OverrideCommandOptions & {
+ videoId: number | string
+ commentId: number
+ }) {
+ const { videoId, commentId } = options
+ const path = '/api/v1/videos/' + videoId + '/comments/' + commentId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
--- /dev/null
+import { HttpStatusCode, ResultList, Video } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class HistoryCommand extends AbstractCommand {
+
+ wathVideo (options: OverrideCommandOptions & {
+ videoId: number | string
+ currentTime: number
+ }) {
+ const { videoId, currentTime } = options
+
+ const path = '/api/v1/videos/' + videoId + '/watching'
+ const fields = { currentTime }
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ list (options: OverrideCommandOptions & {
+ search?: string
+ } = {}) {
+ const { search } = options
+ const path = '/api/v1/users/me/history/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: {
+ search
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ remove (options: OverrideCommandOptions & {
+ beforeDate?: string
+ } = {}) {
+ const { beforeDate } = options
+ const path = '/api/v1/users/me/history/videos/remove'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: { beforeDate },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+}
--- /dev/null
+
+import { HttpStatusCode, ResultList } from '@shared/models'
+import { VideoImport, VideoImportCreate } from '../../models/videos'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ImportsCommand extends AbstractCommand {
+
+ importVideo (options: OverrideCommandOptions & {
+ attributes: VideoImportCreate & { torrentfile?: string }
+ }) {
+ const { attributes } = options
+ const path = '/api/v1/videos/imports'
+
+ let attaches: any = {}
+ if (attributes.torrentfile) attaches = { torrentfile: attributes.torrentfile }
+
+ return unwrapBody<VideoImport>(this.postUploadRequest({
+ ...options,
+
+ path,
+ attaches,
+ fields: options.attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ getMyVideoImports (options: OverrideCommandOptions & {
+ sort?: string
+ } = {}) {
+ const { sort } = options
+ const path = '/api/v1/users/me/videos/imports'
+
+ const query = {}
+ if (sort) query['sort'] = sort
+
+ return this.getRequestBody<ResultList<VideoImport>>({
+ ...options,
+
+ path,
+ query: { sort },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
--- /dev/null
+export * from './blacklist-command'
+export * from './captions-command'
+export * from './captions'
+export * from './change-ownership-command'
+export * from './channels'
+export * from './channels-command'
+export * from './comments-command'
+export * from './history-command'
+export * from './imports-command'
+export * from './live-command'
+export * from './live'
+export * from './playlists-command'
+export * from './playlists'
+export * from './services-command'
+export * from './streaming-playlists-command'
+export * from './streaming-playlists'
+export * from './comments-command'
+export * from './videos-command'
+export * from './videos'
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
+
+import { readdir } from 'fs-extra'
+import { omit } from 'lodash'
+import { join } from 'path'
+import { HttpStatusCode, LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
+import { wait } from '../miscs'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+import { sendRTMPStream, testFfmpegStreamError } from './live'
+
+export class LiveCommand extends AbstractCommand {
+
+ get (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const path = '/api/v1/videos/live'
+
+ return this.getRequestBody<LiveVideo>({
+ ...options,
+
+ path: path + '/' + options.videoId,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ update (options: OverrideCommandOptions & {
+ videoId: number | string
+ fields: LiveVideoUpdate
+ }) {
+ const { videoId, fields } = options
+ const path = '/api/v1/videos/live'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path: path + '/' + videoId,
+ fields,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ async create (options: OverrideCommandOptions & {
+ fields: LiveVideoCreate
+ }) {
+ const { fields } = options
+ const path = '/api/v1/videos/live'
+
+ const attaches: any = {}
+ if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
+ if (fields.previewfile) attaches.previewfile = fields.previewfile
+
+ const body = await unwrapBody<{ video: VideoCreateResult }>(this.postUploadRequest({
+ ...options,
+
+ path,
+ attaches,
+ fields: omit(fields, 'thumbnailfile', 'previewfile'),
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ return body.video
+ }
+
+ async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
+ videoId: number | string
+ fixtureName?: string
+ }) {
+ const { videoId, fixtureName } = options
+ const videoLive = await this.get({ videoId })
+
+ return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, fixtureName)
+ }
+
+ async runAndTestStreamError (options: OverrideCommandOptions & {
+ videoId: number | string
+ shouldHaveError: boolean
+ }) {
+ const command = await this.sendRTMPStreamInVideo(options)
+
+ return testFfmpegStreamError(command, options.shouldHaveError)
+ }
+
+ waitUntilPublished (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const { videoId } = options
+ return this.waitUntilState({ videoId, state: VideoState.PUBLISHED })
+ }
+
+ waitUntilWaiting (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const { videoId } = options
+ return this.waitUntilState({ videoId, state: VideoState.WAITING_FOR_LIVE })
+ }
+
+ waitUntilEnded (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ const { videoId } = options
+ return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED })
+ }
+
+ waitUntilSegmentGeneration (options: OverrideCommandOptions & {
+ videoUUID: string
+ resolution: number
+ segment: number
+ }) {
+ const { resolution, segment, videoUUID } = options
+ const segmentName = `${resolution}-00000${segment}.ts`
+
+ return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, 2, false)
+ }
+
+ async waitUntilSaved (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ let video: VideoDetails
+
+ do {
+ video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
+
+ await wait(500)
+ } while (video.isLive === true && video.state.id !== VideoState.PUBLISHED)
+ }
+
+ async countPlaylists (options: OverrideCommandOptions & {
+ videoUUID: string
+ }) {
+ const basePath = this.server.servers.buildDirectory('streaming-playlists')
+ const hlsPath = join(basePath, 'hls', options.videoUUID)
+
+ const files = await readdir(hlsPath)
+
+ return files.filter(f => f.endsWith('.m3u8')).length
+ }
+
+ private async waitUntilState (options: OverrideCommandOptions & {
+ videoId: number | string
+ state: VideoState
+ }) {
+ let video: VideoDetails
+
+ do {
+ video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
+
+ await wait(500)
+ } while (video.state.id !== options.state)
+ }
+}
import { expect } from 'chai'
import * as ffmpeg from 'fluent-ffmpeg'
import { pathExists, readdir } from 'fs-extra'
-import { omit } from 'lodash'
import { join } from 'path'
-import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-import { buildAbsoluteFixturePath, buildServerDirectory, wait } from '../miscs/miscs'
-import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
-import { ServerInfo, waitUntilLog } from '../server/servers'
-import { getVideoWithToken } from './videos'
-
-function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/videos/live'
-
- return makeGetRequest({
- url,
- token,
- path: path + '/' + videoId,
- statusCodeExpected
- })
-}
-
-function updateLive (
- url: string,
- token: string,
- videoId: number | string,
- fields: LiveVideoUpdate,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/live'
-
- return makePutBodyRequest({
- url,
- token,
- path: path + '/' + videoId,
- fields,
- statusCodeExpected
- })
-}
-
-function createLive (url: string, token: string, fields: LiveVideoCreate, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/videos/live'
-
- const attaches: any = {}
- if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
- if (fields.previewfile) attaches.previewfile = fields.previewfile
-
- const updatedFields = omit(fields, 'thumbnailfile', 'previewfile')
-
- return makeUploadRequest({
- url,
- path,
- token,
- attaches,
- fields: updatedFields,
- statusCodeExpected
- })
-}
-
-async function sendRTMPStreamInVideo (url: string, token: string, videoId: number | string, fixtureName?: string) {
- const res = await getLive(url, token, videoId)
- const videoLive = res.body as LiveVideo
-
- return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, fixtureName)
-}
+import { buildAbsoluteFixturePath, wait } from '../miscs'
+import { PeerTubeServer } from '../server/server'
function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
const fixture = buildAbsoluteFixturePath(fixtureName)
})
}
-async function runAndTestFfmpegStreamError (url: string, token: string, videoId: number | string, shouldHaveError: boolean) {
- const command = await sendRTMPStreamInVideo(url, token, videoId)
-
- return testFfmpegStreamError(command, shouldHaveError)
-}
-
async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) {
let error: Error
await wait(500)
}
-function waitUntilLivePublished (url: string, token: string, videoId: number | string) {
- return waitUntilLiveState(url, token, videoId, VideoState.PUBLISHED)
-}
-
-function waitUntilLiveWaiting (url: string, token: string, videoId: number | string) {
- return waitUntilLiveState(url, token, videoId, VideoState.WAITING_FOR_LIVE)
-}
-
-function waitUntilLiveEnded (url: string, token: string, videoId: number | string) {
- return waitUntilLiveState(url, token, videoId, VideoState.LIVE_ENDED)
-}
-
-function waitUntilLiveSegmentGeneration (server: ServerInfo, videoUUID: string, resolutionNum: number, segmentNum: number) {
- const segmentName = `${resolutionNum}-00000${segmentNum}.ts`
- return waitUntilLog(server, `${videoUUID}/${segmentName}`, 2, false)
-}
-
-async function waitUntilLiveState (url: string, token: string, videoId: number | string, state: VideoState) {
- let video: VideoDetails
-
- do {
- const res = await getVideoWithToken(url, token, videoId)
- video = res.body
-
- await wait(500)
- } while (video.state.id !== state)
-}
-
-async function waitUntilLiveSaved (url: string, token: string, videoId: number | string) {
- let video: VideoDetails
-
- do {
- const res = await getVideoWithToken(url, token, videoId)
- video = res.body
-
- await wait(500)
- } while (video.isLive === true && video.state.id !== VideoState.PUBLISHED)
-}
-
-async function waitUntilLivePublishedOnAllServers (servers: ServerInfo[], videoId: string) {
+async function waitUntilLivePublishedOnAllServers (servers: PeerTubeServer[], videoId: string) {
for (const server of servers) {
- await waitUntilLivePublished(server.url, server.accessToken, videoId)
+ await server.live.waitUntilPublished({ videoId })
}
}
-async function checkLiveCleanup (server: ServerInfo, videoUUID: string, resolutions: number[] = []) {
- const basePath = buildServerDirectory(server, 'streaming-playlists')
+async function checkLiveCleanupAfterSave (server: PeerTubeServer, videoUUID: string, resolutions: number[] = []) {
+ const basePath = server.servers.buildDirectory('streaming-playlists')
const hlsPath = join(basePath, 'hls', videoUUID)
if (resolutions.length === 0) {
expect(files).to.have.lengthOf(resolutions.length * 2 + 2)
for (const resolution of resolutions) {
- expect(files).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`)
- expect(files).to.contain(`${resolution}.m3u8`)
- }
-
- expect(files).to.contain('master.m3u8')
- expect(files).to.contain('segments-sha256.json')
-}
+ const fragmentedFile = files.find(f => f.endsWith(`-${resolution}-fragmented.mp4`))
+ expect(fragmentedFile).to.exist
-async function getPlaylistsCount (server: ServerInfo, videoUUID: string) {
- const basePath = buildServerDirectory(server, 'streaming-playlists')
- const hlsPath = join(basePath, 'hls', videoUUID)
+ const playlistFile = files.find(f => f.endsWith(`${resolution}.m3u8`))
+ expect(playlistFile).to.exist
+ }
- const files = await readdir(hlsPath)
+ const masterPlaylistFile = files.find(f => f.endsWith('-master.m3u8'))
+ expect(masterPlaylistFile).to.exist
- return files.filter(f => f.endsWith('.m3u8')).length
+ const shaFile = files.find(f => f.endsWith('-segments-sha256.json'))
+ expect(shaFile).to.exist
}
-// ---------------------------------------------------------------------------
-
export {
- getLive,
- getPlaylistsCount,
- waitUntilLiveSaved,
- waitUntilLivePublished,
- updateLive,
- createLive,
- runAndTestFfmpegStreamError,
- checkLiveCleanup,
- waitUntilLiveSegmentGeneration,
- stopFfmpeg,
- waitUntilLiveWaiting,
- sendRTMPStreamInVideo,
- waitUntilLiveEnded,
+ sendRTMPStream,
waitFfmpegUntilError,
+ testFfmpegStreamError,
+ stopFfmpeg,
waitUntilLivePublishedOnAllServers,
- sendRTMPStream,
- testFfmpegStreamError
+ checkLiveCleanupAfterSave
}
--- /dev/null
+import { omit } from 'lodash'
+import { pick } from '@shared/core-utils'
+import {
+ BooleanBothQuery,
+ HttpStatusCode,
+ ResultList,
+ VideoExistInPlaylist,
+ VideoPlaylist,
+ VideoPlaylistCreate,
+ VideoPlaylistCreateResult,
+ VideoPlaylistElement,
+ VideoPlaylistElementCreate,
+ VideoPlaylistElementCreateResult,
+ VideoPlaylistElementUpdate,
+ VideoPlaylistReorder,
+ VideoPlaylistType,
+ VideoPlaylistUpdate
+} from '@shared/models'
+import { unwrapBody } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class PlaylistsCommand extends AbstractCommand {
+
+ list (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ }) {
+ const path = '/api/v1/video-playlists'
+ const query = pick(options, [ 'start', 'count', 'sort' ])
+
+ return this.getRequestBody<ResultList<VideoPlaylist>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listByChannel (options: OverrideCommandOptions & {
+ handle: string
+ start?: number
+ count?: number
+ sort?: string
+ }) {
+ const path = '/api/v1/video-channels/' + options.handle + '/video-playlists'
+ const query = pick(options, [ 'start', 'count', 'sort' ])
+
+ return this.getRequestBody<ResultList<VideoPlaylist>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listByAccount (options: OverrideCommandOptions & {
+ handle: string
+ start?: number
+ count?: number
+ sort?: string
+ search?: string
+ playlistType?: VideoPlaylistType
+ }) {
+ const path = '/api/v1/accounts/' + options.handle + '/video-playlists'
+ const query = pick(options, [ 'start', 'count', 'sort', 'search', 'playlistType' ])
+
+ return this.getRequestBody<ResultList<VideoPlaylist>>({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ get (options: OverrideCommandOptions & {
+ playlistId: number | string
+ }) {
+ const { playlistId } = options
+ const path = '/api/v1/video-playlists/' + playlistId
+
+ return this.getRequestBody<VideoPlaylist>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listVideos (options: OverrideCommandOptions & {
+ playlistId: number | string
+ start?: number
+ count?: number
+ query?: { nsfw?: BooleanBothQuery }
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
+ const query = options.query ?? {}
+
+ return this.getRequestBody<ResultList<VideoPlaylistElement>>({
+ ...options,
+
+ path,
+ query: {
+ ...query,
+ start: options.start,
+ count: options.count
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ delete (options: OverrideCommandOptions & {
+ playlistId: number | string
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ async create (options: OverrideCommandOptions & {
+ attributes: VideoPlaylistCreate
+ }) {
+ const path = '/api/v1/video-playlists'
+
+ const fields = omit(options.attributes, 'thumbnailfile')
+
+ const attaches = options.attributes.thumbnailfile
+ ? { thumbnailfile: options.attributes.thumbnailfile }
+ : {}
+
+ const body = await unwrapBody<{ videoPlaylist: VideoPlaylistCreateResult }>(this.postUploadRequest({
+ ...options,
+
+ path,
+ fields,
+ attaches,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ return body.videoPlaylist
+ }
+
+ update (options: OverrideCommandOptions & {
+ attributes: VideoPlaylistUpdate
+ playlistId: number | string
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId
+
+ const fields = omit(options.attributes, 'thumbnailfile')
+
+ const attaches = options.attributes.thumbnailfile
+ ? { thumbnailfile: options.attributes.thumbnailfile }
+ : {}
+
+ return this.putUploadRequest({
+ ...options,
+
+ path,
+ fields,
+ attaches,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ async addElement (options: OverrideCommandOptions & {
+ playlistId: number | string
+ attributes: VideoPlaylistElementCreate | { videoId: string }
+ }) {
+ const attributes = {
+ ...options.attributes,
+
+ videoId: await this.server.videos.getId({ ...options, uuid: options.attributes.videoId })
+ }
+
+ const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
+
+ const body = await unwrapBody<{ videoPlaylistElement: VideoPlaylistElementCreateResult }>(this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+
+ return body.videoPlaylistElement
+ }
+
+ updateElement (options: OverrideCommandOptions & {
+ playlistId: number | string
+ elementId: number | string
+ attributes: VideoPlaylistElementUpdate
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.elementId
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: options.attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ removeElement (options: OverrideCommandOptions & {
+ playlistId: number | string
+ elementId: number
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.elementId
+
+ return this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ reorderElements (options: OverrideCommandOptions & {
+ playlistId: number | string
+ attributes: VideoPlaylistReorder
+ }) {
+ const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/reorder'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ fields: options.attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ getPrivacies (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/video-playlists/privacies'
+
+ return this.getRequestBody<{ [ id: number ]: string }>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ videosExist (options: OverrideCommandOptions & {
+ videoIds: number[]
+ }) {
+ const { videoIds } = options
+ const path = '/api/v1/users/me/video-playlists/videos-exist'
+
+ return this.getRequestBody<VideoExistInPlaylist>({
+ ...options,
+
+ path,
+ query: { videoIds },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
--- /dev/null
+import { expect } from 'chai'
+import { readdir } from 'fs-extra'
+import { join } from 'path'
+import { root } from '../miscs'
+
+async function checkPlaylistFilesWereRemoved (
+ playlistUUID: string,
+ internalServerNumber: number,
+ directories = [ 'thumbnails' ]
+) {
+ const testDirectory = 'test' + internalServerNumber
+
+ for (const directory of directories) {
+ const directoryPath = join(root(), testDirectory, directory)
+
+ const files = await readdir(directoryPath)
+ for (const file of files) {
+ expect(file).to.not.contain(playlistUUID)
+ }
+ }
+}
+
+export {
+ checkPlaylistFilesWereRemoved
+}
--- /dev/null
+import { HttpStatusCode } from '@shared/models'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class ServicesCommand extends AbstractCommand {
+
+ getOEmbed (options: OverrideCommandOptions & {
+ oembedUrl: string
+ format?: string
+ maxHeight?: number
+ maxWidth?: number
+ }) {
+ const path = '/services/oembed'
+ const query = {
+ url: options.oembedUrl,
+ format: options.format,
+ maxheight: options.maxHeight,
+ maxwidth: options.maxWidth
+ }
+
+ return this.getRequest({
+ ...options,
+
+ path,
+ query,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+}
+++ /dev/null
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getOEmbed (url: string, oembedUrl: string, format?: string, maxHeight?: number, maxWidth?: number) {
- const path = '/services/oembed'
- const query = {
- url: oembedUrl,
- format,
- maxheight: maxHeight,
- maxwidth: maxWidth
- }
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getOEmbed
-}
--- /dev/null
+import { HttpStatusCode } from '@shared/models'
+import { unwrapBody, unwrapText } from '../requests'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export class StreamingPlaylistsCommand extends AbstractCommand {
+
+ get (options: OverrideCommandOptions & {
+ url: string
+ }) {
+ return unwrapText(this.getRawRequest({
+ ...options,
+
+ url: options.url,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ getSegment (options: OverrideCommandOptions & {
+ url: string
+ range?: string
+ }) {
+ return unwrapBody<Buffer>(this.getRawRequest({
+ ...options,
+
+ url: options.url,
+ range: options.range,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ getSegmentSha256 (options: OverrideCommandOptions & {
+ url: string
+ }) {
+ return unwrapBody<{ [ id: string ]: string }>(this.getRawRequest({
+ ...options,
+
+ url: options.url,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+}
--- /dev/null
+import { expect } from 'chai'
+import { basename } from 'path'
+import { sha256 } from '@server/helpers/core-utils'
+import { removeFragmentedMP4Ext } from '@shared/core-utils'
+import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models'
+import { PeerTubeServer } from '../server'
+
+async function checkSegmentHash (options: {
+ server: PeerTubeServer
+ baseUrlPlaylist: string
+ baseUrlSegment: string
+ videoUUID: string
+ resolution: number
+ hlsPlaylist: VideoStreamingPlaylist
+}) {
+ const { server, baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist } = options
+ const command = server.streamingPlaylists
+
+ const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
+ const videoName = basename(file.fileUrl)
+
+ const playlist = await command.get({ url: `${baseUrlPlaylist}/${videoUUID}/${removeFragmentedMP4Ext(videoName)}.m3u8` })
+
+ const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
+
+ const length = parseInt(matches[1], 10)
+ const offset = parseInt(matches[2], 10)
+ const range = `${offset}-${offset + length - 1}`
+
+ const segmentBody = await command.getSegment({
+ url: `${baseUrlSegment}/${videoUUID}/${videoName}`,
+ expectedStatus: HttpStatusCode.PARTIAL_CONTENT_206,
+ range: `bytes=${range}`
+ })
+
+ const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
+ expect(sha256(segmentBody)).to.equal(shaBody[videoName][range])
+}
+
+async function checkLiveSegmentHash (options: {
+ server: PeerTubeServer
+ baseUrlSegment: string
+ videoUUID: string
+ segmentName: string
+ hlsPlaylist: VideoStreamingPlaylist
+}) {
+ const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist } = options
+ const command = server.streamingPlaylists
+
+ const segmentBody = await command.getSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}` })
+ const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
+
+ expect(sha256(segmentBody)).to.equal(shaBody[segmentName])
+}
+
+async function checkResolutionsInMasterPlaylist (options: {
+ server: PeerTubeServer
+ playlistUrl: string
+ resolutions: number[]
+}) {
+ const { server, playlistUrl, resolutions } = options
+
+ const masterPlaylist = await server.streamingPlaylists.get({ url: playlistUrl })
+
+ for (const resolution of resolutions) {
+ const reg = new RegExp(
+ '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"'
+ )
+
+ expect(masterPlaylist).to.match(reg)
+ }
+}
+
+export {
+ checkSegmentHash,
+ checkLiveSegmentHash,
+ checkResolutionsInMasterPlaylist
+}
+++ /dev/null
-import * as request from 'supertest'
-import { VideoBlacklistType } from '../../models/videos'
-import { makeGetRequest } from '..'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function addVideoToBlacklist (
- url: string,
- token: string,
- videoId: number | string,
- reason?: string,
- unfederate?: boolean,
- specialStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + videoId + '/blacklist'
-
- return request(url)
- .post(path)
- .send({ reason, unfederate })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(specialStatus)
-}
-
-function updateVideoBlacklist (
- url: string,
- token: string,
- videoId: number,
- reason?: string,
- specialStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + videoId + '/blacklist'
-
- return request(url)
- .put(path)
- .send({ reason })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(specialStatus)
-}
-
-function removeVideoFromBlacklist (url: string, token: string, videoId: number | string, specialStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/videos/' + videoId + '/blacklist'
-
- return request(url)
- .delete(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(specialStatus)
-}
-
-function getBlacklistedVideosList (parameters: {
- url: string
- token: string
- sort?: string
- type?: VideoBlacklistType
- specialStatus?: HttpStatusCode
-}) {
- const { url, token, sort, type, specialStatus = HttpStatusCode.OK_200 } = parameters
- const path = '/api/v1/videos/blacklist/'
-
- const query = { sort, type }
-
- return makeGetRequest({
- url,
- path,
- query,
- token,
- statusCodeExpected: specialStatus
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- addVideoToBlacklist,
- removeVideoFromBlacklist,
- getBlacklistedVideosList,
- updateVideoBlacklist
-}
+++ /dev/null
-import { makeDeleteRequest, makeGetRequest, makeUploadRequest } from '../requests/requests'
-import * as request from 'supertest'
-import * as chai from 'chai'
-import { buildAbsoluteFixturePath } from '../miscs/miscs'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-const expect = chai.expect
-
-function createVideoCaption (args: {
- url: string
- accessToken: string
- videoId: string | number
- language: string
- fixture: string
- mimeType?: string
- statusCodeExpected?: number
-}) {
- const path = '/api/v1/videos/' + args.videoId + '/captions/' + args.language
-
- const captionfile = buildAbsoluteFixturePath(args.fixture)
- const captionfileAttach = args.mimeType ? [ captionfile, { contentType: args.mimeType } ] : captionfile
-
- return makeUploadRequest({
- method: 'PUT',
- url: args.url,
- path,
- token: args.accessToken,
- fields: {},
- attaches: {
- captionfile: captionfileAttach
- },
- statusCodeExpected: args.statusCodeExpected || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function listVideoCaptions (url: string, videoId: string | number) {
- const path = '/api/v1/videos/' + videoId + '/captions'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function deleteVideoCaption (url: string, token: string, videoId: string | number, language: string) {
- const path = '/api/v1/videos/' + videoId + '/captions/' + language
-
- return makeDeleteRequest({
- url,
- token,
- path,
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-async function testCaptionFile (url: string, captionPath: string, containsString: string) {
- const res = await request(url)
- .get(captionPath)
- .expect(HttpStatusCode.OK_200)
-
- expect(res.text).to.contain(containsString)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- createVideoCaption,
- listVideoCaptions,
- testCaptionFile,
- deleteVideoCaption
-}
+++ /dev/null
-import * as request from 'supertest'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function changeVideoOwnership (
- url: string,
- token: string,
- videoId: number | string,
- username,
- expectedStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + videoId + '/give-ownership'
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .send({ username })
- .expect(expectedStatus)
-}
-
-function getVideoChangeOwnershipList (url: string, token: string) {
- const path = '/api/v1/videos/ownership'
-
- return request(url)
- .get(path)
- .query({ sort: '-createdAt' })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function acceptChangeOwnership (
- url: string,
- token: string,
- ownershipId: string,
- channelId: number,
- expectedStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/ownership/' + ownershipId + '/accept'
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .send({ channelId })
- .expect(expectedStatus)
-}
-
-function refuseChangeOwnership (
- url: string,
- token: string,
- ownershipId: string,
- expectedStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/ownership/' + ownershipId + '/refuse'
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- changeVideoOwnership,
- getVideoChangeOwnershipList,
- acceptChangeOwnership,
- refuseChangeOwnership
-}
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-floating-promises */
-
-import * as request from 'supertest'
-import { VideoChannelUpdate } from '../../models/videos/channel/video-channel-update.model'
-import { VideoChannelCreate } from '../../models/videos/channel/video-channel-create.model'
-import { makeDeleteRequest, makeGetRequest, updateImageRequest } from '../requests/requests'
-import { ServerInfo } from '../server/servers'
-import { MyUser, User } from '../../models/users/user.model'
-import { getMyUserInformation } from '../users/users'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getVideoChannelsList (url: string, start: number, count: number, sort?: string, withStats?: boolean) {
- const path = '/api/v1/video-channels'
-
- const req = request(url)
- .get(path)
- .query({ start: start })
- .query({ count: count })
-
- if (sort) req.query({ sort })
- if (withStats) req.query({ withStats })
-
- return req.set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getAccountVideoChannelsList (parameters: {
- url: string
- accountName: string
- start?: number
- count?: number
- sort?: string
- specialStatus?: HttpStatusCode
- withStats?: boolean
- search?: string
-}) {
- const {
- url,
- accountName,
- start,
- count,
- sort = 'createdAt',
- specialStatus = HttpStatusCode.OK_200,
- withStats = false,
- search
- } = parameters
-
- const path = '/api/v1/accounts/' + accountName + '/video-channels'
-
- return makeGetRequest({
- url,
- path,
- query: {
- start,
- count,
- sort,
- withStats,
- search
- },
- statusCodeExpected: specialStatus
- })
-}
-
-function addVideoChannel (
- url: string,
- token: string,
- videoChannelAttributesArg: VideoChannelCreate,
- expectedStatus = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/video-channels/'
-
- // Default attributes
- let attributes = {
- displayName: 'my super video channel',
- description: 'my super channel description',
- support: 'my super channel support'
- }
- attributes = Object.assign(attributes, videoChannelAttributesArg)
-
- return request(url)
- .post(path)
- .send(attributes)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-function updateVideoChannel (
- url: string,
- token: string,
- channelName: string,
- attributes: VideoChannelUpdate,
- expectedStatus = HttpStatusCode.NO_CONTENT_204
-) {
- const body: any = {}
- const path = '/api/v1/video-channels/' + channelName
-
- if (attributes.displayName) body.displayName = attributes.displayName
- if (attributes.description) body.description = attributes.description
- if (attributes.support) body.support = attributes.support
- if (attributes.bulkVideosSupportUpdate) body.bulkVideosSupportUpdate = attributes.bulkVideosSupportUpdate
-
- return request(url)
- .put(path)
- .send(body)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-function deleteVideoChannel (url: string, token: string, channelName: string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/video-channels/' + channelName
-
- return request(url)
- .delete(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-function getVideoChannel (url: string, channelName: string) {
- const path = '/api/v1/video-channels/' + channelName
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function updateVideoChannelImage (options: {
- url: string
- accessToken: string
- fixture: string
- videoChannelName: string | number
- type: 'avatar' | 'banner'
-}) {
- const path = `/api/v1/video-channels/${options.videoChannelName}/${options.type}/pick`
-
- return updateImageRequest({ ...options, path, fieldname: options.type + 'file' })
-}
-
-function deleteVideoChannelImage (options: {
- url: string
- accessToken: string
- videoChannelName: string | number
- type: 'avatar' | 'banner'
-}) {
- const path = `/api/v1/video-channels/${options.videoChannelName}/${options.type}`
-
- return makeDeleteRequest({
- url: options.url,
- token: options.accessToken,
- path,
- statusCodeExpected: 204
- })
-}
-
-function setDefaultVideoChannel (servers: ServerInfo[]) {
- const tasks: Promise<any>[] = []
-
- for (const server of servers) {
- const p = getMyUserInformation(server.url, server.accessToken)
- .then(res => { server.videoChannel = (res.body as User).videoChannels[0] })
-
- tasks.push(p)
- }
-
- return Promise.all(tasks)
-}
-
-async function getDefaultVideoChannel (url: string, token: string) {
- const res = await getMyUserInformation(url, token)
-
- return (res.body as MyUser).videoChannels[0].id
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- updateVideoChannelImage,
- getVideoChannelsList,
- getAccountVideoChannelsList,
- addVideoChannel,
- updateVideoChannel,
- deleteVideoChannel,
- getVideoChannel,
- setDefaultVideoChannel,
- deleteVideoChannelImage,
- getDefaultVideoChannel
-}
+++ /dev/null
-/* eslint-disable @typescript-eslint/no-floating-promises */
-
-import * as request from 'supertest'
-import { makeDeleteRequest, makeGetRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getAdminVideoComments (options: {
- url: string
- token: string
- start: number
- count: number
- sort?: string
- isLocal?: boolean
- search?: string
- searchAccount?: string
- searchVideo?: string
-}) {
- const { url, token, start, count, sort, isLocal, search, searchAccount, searchVideo } = options
- const path = '/api/v1/videos/comments'
-
- const query = {
- start,
- count,
- sort: sort || '-createdAt'
- }
-
- if (isLocal !== undefined) Object.assign(query, { isLocal })
- if (search !== undefined) Object.assign(query, { search })
- if (searchAccount !== undefined) Object.assign(query, { searchAccount })
- if (searchVideo !== undefined) Object.assign(query, { searchVideo })
-
- return makeGetRequest({
- url,
- path,
- token,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string, token?: string) {
- const path = '/api/v1/videos/' + videoId + '/comment-threads'
-
- const req = request(url)
- .get(path)
- .query({ start: start })
- .query({ count: count })
-
- if (sort) req.query({ sort })
- if (token) req.set('Authorization', 'Bearer ' + token)
-
- return req.set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getVideoThreadComments (url: string, videoId: number | string, threadId: number, token?: string) {
- const path = '/api/v1/videos/' + videoId + '/comment-threads/' + threadId
-
- const req = request(url)
- .get(path)
- .set('Accept', 'application/json')
-
- if (token) req.set('Authorization', 'Bearer ' + token)
-
- return req.expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function addVideoCommentThread (
- url: string,
- token: string,
- videoId: number | string,
- text: string,
- expectedStatus = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/videos/' + videoId + '/comment-threads'
-
- return request(url)
- .post(path)
- .send({ text })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-function addVideoCommentReply (
- url: string,
- token: string,
- videoId: number | string,
- inReplyToCommentId: number,
- text: string,
- expectedStatus = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/videos/' + videoId + '/comments/' + inReplyToCommentId
-
- return request(url)
- .post(path)
- .send({ text })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
-
-async function findCommentId (url: string, videoId: number | string, text: string) {
- const res = await getVideoCommentThreads(url, videoId, 0, 25, '-createdAt')
-
- return res.body.data.find(c => c.text === text).id as number
-}
-
-function deleteVideoComment (
- url: string,
- token: string,
- videoId: number | string,
- commentId: number,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + videoId + '/comments/' + commentId
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getVideoCommentThreads,
- getAdminVideoComments,
- getVideoThreadComments,
- addVideoCommentThread,
- addVideoCommentReply,
- findCommentId,
- deleteVideoComment
-}
+++ /dev/null
-import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function userWatchVideo (
- url: string,
- token: string,
- videoId: number | string,
- currentTime: number,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + videoId + '/watching'
- const fields = { currentTime }
-
- return makePutBodyRequest({ url, path, token, fields, statusCodeExpected })
-}
-
-function listMyVideosHistory (url: string, token: string, search?: string) {
- const path = '/api/v1/users/me/history/videos'
-
- return makeGetRequest({
- url,
- path,
- token,
- query: {
- search
- },
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function removeMyVideosHistory (url: string, token: string, beforeDate?: string) {
- const path = '/api/v1/users/me/history/videos/remove'
-
- return makePostBodyRequest({
- url,
- path,
- token,
- fields: beforeDate ? { beforeDate } : {},
- statusCodeExpected: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- userWatchVideo,
- listMyVideosHistory,
- removeMyVideosHistory
-}
+++ /dev/null
-
-import { VideoImportCreate } from '../../models/videos'
-import { makeGetRequest, makeUploadRequest } from '../requests/requests'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getYoutubeVideoUrl () {
- return 'https://www.youtube.com/watch?v=msX3jv1XdvM'
-}
-
-function getYoutubeHDRVideoUrl () {
- /**
- * The video is used to check format-selection correctness wrt. HDR,
- * which brings its own set of oddities outside of a MediaSource.
- * FIXME: refactor once HDR is supported at playback
- *
- * The video needs to have the following format_ids:
- * (which you can check by using `youtube-dl <url> -F`):
- * - 303 (1080p webm vp9)
- * - 299 (1080p mp4 avc1)
- * - 335 (1080p webm vp9.2 HDR)
- *
- * 15 jan. 2021: TEST VIDEO NOT CURRENTLY PROVIDING
- * - 400 (1080p mp4 av01)
- * - 315 (2160p webm vp9 HDR)
- * - 337 (2160p webm vp9.2 HDR)
- * - 401 (2160p mp4 av01 HDR)
- */
- return 'https://www.youtube.com/watch?v=qR5vOXbZsI4'
-}
-
-function getMagnetURI () {
- // eslint-disable-next-line max-len
- return 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4'
-}
-
-function getBadVideoUrl () {
- return 'https://download.cpy.re/peertube/bad_video.mp4'
-}
-
-function getGoodVideoUrl () {
- return 'https://download.cpy.re/peertube/good_video.mp4'
-}
-
-function importVideo (
- url: string,
- token: string,
- attributes: VideoImportCreate & { torrentfile?: string },
- statusCodeExpected = HttpStatusCode.OK_200
-) {
- const path = '/api/v1/videos/imports'
-
- let attaches: any = {}
- if (attributes.torrentfile) attaches = { torrentfile: attributes.torrentfile }
-
- return makeUploadRequest({
- url,
- path,
- token,
- attaches,
- fields: attributes,
- statusCodeExpected
- })
-}
-
-function getMyVideoImports (url: string, token: string, sort?: string) {
- const path = '/api/v1/users/me/videos/imports'
-
- const query = {}
- if (sort) query['sort'] = sort
-
- return makeGetRequest({
- url,
- query,
- path,
- token,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getBadVideoUrl,
- getYoutubeVideoUrl,
- getYoutubeHDRVideoUrl,
- importVideo,
- getMagnetURI,
- getMyVideoImports,
- getGoodVideoUrl
-}
+++ /dev/null
-import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
-import { VideoPlaylistCreate } from '../../models/videos/playlist/video-playlist-create.model'
-import { omit } from 'lodash'
-import { VideoPlaylistUpdate } from '../../models/videos/playlist/video-playlist-update.model'
-import { VideoPlaylistElementCreate } from '../../models/videos/playlist/video-playlist-element-create.model'
-import { VideoPlaylistElementUpdate } from '../../models/videos/playlist/video-playlist-element-update.model'
-import { videoUUIDToId } from './videos'
-import { join } from 'path'
-import { root } from '..'
-import { readdir } from 'fs-extra'
-import { expect } from 'chai'
-import { VideoPlaylistType } from '../../models/videos/playlist/video-playlist-type.model'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getVideoPlaylistsList (url: string, start: number, count: number, sort?: string) {
- const path = '/api/v1/video-playlists'
-
- const query = {
- start,
- count,
- sort
- }
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoChannelPlaylistsList (url: string, videoChannelName: string, start: number, count: number, sort?: string) {
- const path = '/api/v1/video-channels/' + videoChannelName + '/video-playlists'
-
- const query = {
- start,
- count,
- sort
- }
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getAccountPlaylistsList (url: string, accountName: string, start: number, count: number, sort?: string, search?: string) {
- const path = '/api/v1/accounts/' + accountName + '/video-playlists'
-
- const query = {
- start,
- count,
- sort,
- search
- }
-
- return makeGetRequest({
- url,
- path,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getAccountPlaylistsListWithToken (
- url: string,
- token: string,
- accountName: string,
- start: number,
- count: number,
- playlistType?: VideoPlaylistType,
- sort?: string
-) {
- const path = '/api/v1/accounts/' + accountName + '/video-playlists'
-
- const query = {
- start,
- count,
- playlistType,
- sort
- }
-
- return makeGetRequest({
- url,
- token,
- path,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoPlaylist (url: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/video-playlists/' + playlistId
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected
- })
-}
-
-function getVideoPlaylistWithToken (url: string, token: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
- const path = '/api/v1/video-playlists/' + playlistId
-
- return makeGetRequest({
- url,
- token,
- path,
- statusCodeExpected
- })
-}
-
-function deleteVideoPlaylist (url: string, token: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/video-playlists/' + playlistId
-
- return makeDeleteRequest({
- url,
- path,
- token,
- statusCodeExpected
- })
-}
-
-function createVideoPlaylist (options: {
- url: string
- token: string
- playlistAttrs: VideoPlaylistCreate
- expectedStatus?: number
-}) {
- const path = '/api/v1/video-playlists'
-
- const fields = omit(options.playlistAttrs, 'thumbnailfile')
-
- const attaches = options.playlistAttrs.thumbnailfile
- ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
- : {}
-
- return makeUploadRequest({
- method: 'POST',
- url: options.url,
- path,
- token: options.token,
- fields,
- attaches,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.OK_200
- })
-}
-
-function updateVideoPlaylist (options: {
- url: string
- token: string
- playlistAttrs: VideoPlaylistUpdate
- playlistId: number | string
- expectedStatus?: number
-}) {
- const path = '/api/v1/video-playlists/' + options.playlistId
-
- const fields = omit(options.playlistAttrs, 'thumbnailfile')
-
- const attaches = options.playlistAttrs.thumbnailfile
- ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
- : {}
-
- return makeUploadRequest({
- method: 'PUT',
- url: options.url,
- path,
- token: options.token,
- fields,
- attaches,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-async function addVideoInPlaylist (options: {
- url: string
- token: string
- playlistId: number | string
- elementAttrs: VideoPlaylistElementCreate | { videoId: string }
- expectedStatus?: number
-}) {
- options.elementAttrs.videoId = await videoUUIDToId(options.url, options.elementAttrs.videoId)
-
- const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
-
- return makePostBodyRequest({
- url: options.url,
- path,
- token: options.token,
- fields: options.elementAttrs,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.OK_200
- })
-}
-
-function updateVideoPlaylistElement (options: {
- url: string
- token: string
- playlistId: number | string
- playlistElementId: number | string
- elementAttrs: VideoPlaylistElementUpdate
- expectedStatus?: number
-}) {
- const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.playlistElementId
-
- return makePutBodyRequest({
- url: options.url,
- path,
- token: options.token,
- fields: options.elementAttrs,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function removeVideoFromPlaylist (options: {
- url: string
- token: string
- playlistId: number | string
- playlistElementId: number
- expectedStatus?: number
-}) {
- const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.playlistElementId
-
- return makeDeleteRequest({
- url: options.url,
- path,
- token: options.token,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-function reorderVideosPlaylist (options: {
- url: string
- token: string
- playlistId: number | string
- elementAttrs: {
- startPosition: number
- insertAfterPosition: number
- reorderLength?: number
- }
- expectedStatus?: number
-}) {
- const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/reorder'
-
- return makePostBodyRequest({
- url: options.url,
- path,
- token: options.token,
- fields: options.elementAttrs,
- statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
- })
-}
-
-async function checkPlaylistFilesWereRemoved (
- playlistUUID: string,
- internalServerNumber: number,
- directories = [ 'thumbnails' ]
-) {
- const testDirectory = 'test' + internalServerNumber
-
- for (const directory of directories) {
- const directoryPath = join(root(), testDirectory, directory)
-
- const files = await readdir(directoryPath)
- for (const file of files) {
- expect(file).to.not.contain(playlistUUID)
- }
- }
-}
-
-function getVideoPlaylistPrivacies (url: string) {
- const path = '/api/v1/video-playlists/privacies'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function doVideosExistInMyPlaylist (url: string, token: string, videoIds: number[]) {
- const path = '/api/v1/users/me/video-playlists/videos-exist'
-
- return makeGetRequest({
- url,
- token,
- path,
- query: { videoIds },
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getVideoPlaylistPrivacies,
-
- getVideoPlaylistsList,
- getVideoChannelPlaylistsList,
- getAccountPlaylistsList,
- getAccountPlaylistsListWithToken,
-
- getVideoPlaylist,
- getVideoPlaylistWithToken,
-
- createVideoPlaylist,
- updateVideoPlaylist,
- deleteVideoPlaylist,
-
- addVideoInPlaylist,
- updateVideoPlaylistElement,
- removeVideoFromPlaylist,
-
- reorderVideosPlaylist,
-
- checkPlaylistFilesWereRemoved,
-
- doVideosExistInMyPlaylist
-}
+++ /dev/null
-import { makeRawRequest } from '../requests/requests'
-import { sha256 } from '../../../server/helpers/core-utils'
-import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model'
-import { expect } from 'chai'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
-
-function getPlaylist (url: string, statusCodeExpected = HttpStatusCode.OK_200) {
- return makeRawRequest(url, statusCodeExpected)
-}
-
-function getSegment (url: string, statusCodeExpected = HttpStatusCode.OK_200, range?: string) {
- return makeRawRequest(url, statusCodeExpected, range)
-}
-
-function getSegmentSha256 (url: string, statusCodeExpected = HttpStatusCode.OK_200) {
- return makeRawRequest(url, statusCodeExpected)
-}
-
-async function checkSegmentHash (
- baseUrlPlaylist: string,
- baseUrlSegment: string,
- videoUUID: string,
- resolution: number,
- hlsPlaylist: VideoStreamingPlaylist
-) {
- const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`)
- const playlist = res.text
-
- const videoName = `${videoUUID}-${resolution}-fragmented.mp4`
-
- const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
-
- const length = parseInt(matches[1], 10)
- const offset = parseInt(matches[2], 10)
- const range = `${offset}-${offset + length - 1}`
-
- const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, HttpStatusCode.PARTIAL_CONTENT_206, `bytes=${range}`)
-
- const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url)
-
- const sha256Server = resSha.body[videoName][range]
- expect(sha256(res2.body)).to.equal(sha256Server)
-}
-
-async function checkLiveSegmentHash (
- baseUrlSegment: string,
- videoUUID: string,
- segmentName: string,
- hlsPlaylist: VideoStreamingPlaylist
-) {
- const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${segmentName}`)
-
- const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url)
-
- const sha256Server = resSha.body[segmentName]
- expect(sha256(res2.body)).to.equal(sha256Server)
-}
-
-async function checkResolutionsInMasterPlaylist (playlistUrl: string, resolutions: number[]) {
- const res = await getPlaylist(playlistUrl)
-
- const masterPlaylist = res.text
-
- for (const resolution of resolutions) {
- const reg = new RegExp(
- '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"'
- )
-
- expect(masterPlaylist).to.match(reg)
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getPlaylist,
- getSegment,
- checkResolutionsInMasterPlaylist,
- getSegmentSha256,
- checkLiveSegmentHash,
- checkSegmentHash
-}
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
+
+import { expect } from 'chai'
+import { createReadStream, stat } from 'fs-extra'
+import got, { Response as GotResponse } from 'got'
+import { omit } from 'lodash'
+import validator from 'validator'
+import { buildUUID } from '@server/helpers/uuid'
+import { loadLanguages } from '@server/initializers/constants'
+import { pick } from '@shared/core-utils'
+import {
+ HttpStatusCode,
+ ResultList,
+ UserVideoRateType,
+ Video,
+ VideoCreate,
+ VideoCreateResult,
+ VideoDetails,
+ VideoFileMetadata,
+ VideoPrivacy,
+ VideosCommonQuery,
+ VideosWithSearchCommonQuery
+} from '@shared/models'
+import { buildAbsoluteFixturePath, wait } from '../miscs'
+import { unwrapBody } from '../requests'
+import { PeerTubeServer, waitJobs } from '../server'
+import { AbstractCommand, OverrideCommandOptions } from '../shared'
+
+export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile'>> & {
+ fixture?: string
+ thumbnailfile?: string
+ previewfile?: string
+}
+
+export class VideosCommand extends AbstractCommand {
+
+ constructor (server: PeerTubeServer) {
+ super(server)
+
+ loadLanguages()
+ }
+
+ getCategories (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/videos/categories'
+
+ return this.getRequestBody<{ [id: number]: string }>({
+ ...options,
+ path,
+
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getLicences (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/videos/licences'
+
+ return this.getRequestBody<{ [id: number]: string }>({
+ ...options,
+ path,
+
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getLanguages (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/videos/languages'
+
+ return this.getRequestBody<{ [id: string]: string }>({
+ ...options,
+ path,
+
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getPrivacies (options: OverrideCommandOptions = {}) {
+ const path = '/api/v1/videos/privacies'
+
+ return this.getRequestBody<{ [id in VideoPrivacy]: string }>({
+ ...options,
+ path,
+
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ getDescription (options: OverrideCommandOptions & {
+ descriptionPath: string
+ }) {
+ return this.getRequestBody<{ description: string }>({
+ ...options,
+ path: options.descriptionPath,
+
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getFileMetadata (options: OverrideCommandOptions & {
+ url: string
+ }) {
+ return unwrapBody<VideoFileMetadata>(this.getRawRequest({
+ ...options,
+
+ url: options.url,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ }))
+ }
+
+ // ---------------------------------------------------------------------------
+
+ view (options: OverrideCommandOptions & {
+ id: number | string
+ xForwardedFor?: string
+ }) {
+ const { id, xForwardedFor } = options
+ const path = '/api/v1/videos/' + id + '/views'
+
+ return this.postBodyRequest({
+ ...options,
+
+ path,
+ xForwardedFor,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ rate (options: OverrideCommandOptions & {
+ id: number | string
+ rating: UserVideoRateType
+ }) {
+ const { id, rating } = options
+ const path = '/api/v1/videos/' + id + '/rate'
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: { rating },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ get (options: OverrideCommandOptions & {
+ id: number | string
+ }) {
+ const path = '/api/v1/videos/' + options.id
+
+ return this.getRequestBody<VideoDetails>({
+ ...options,
+
+ path,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ getWithToken (options: OverrideCommandOptions & {
+ id: number | string
+ }) {
+ return this.get({
+ ...options,
+
+ token: this.buildCommonRequestToken({ ...options, implicitToken: true })
+ })
+ }
+
+ async getId (options: OverrideCommandOptions & {
+ uuid: number | string
+ }) {
+ const { uuid } = options
+
+ if (validator.isUUID('' + uuid) === false) return uuid as number
+
+ const { id } = await this.get({ ...options, id: uuid })
+
+ return id
+ }
+
+ // ---------------------------------------------------------------------------
+
+ listMyVideos (options: OverrideCommandOptions & {
+ start?: number
+ count?: number
+ sort?: string
+ search?: string
+ isLive?: boolean
+ } = {}) {
+ const path = '/api/v1/users/me/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: pick(options, [ 'start', 'count', 'sort', 'search', 'isLive' ]),
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ list (options: OverrideCommandOptions & VideosCommonQuery = {}) {
+ const path = '/api/v1/videos'
+
+ const query = this.buildListQuery(options)
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: { sort: 'name', ...query },
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listWithToken (options: OverrideCommandOptions & VideosCommonQuery = {}) {
+ return this.list({
+ ...options,
+
+ token: this.buildCommonRequestToken({ ...options, implicitToken: true })
+ })
+ }
+
+ listByAccount (options: OverrideCommandOptions & VideosWithSearchCommonQuery & {
+ handle: string
+ }) {
+ const { handle, search } = options
+ const path = '/api/v1/accounts/' + handle + '/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: { search, ...this.buildListQuery(options) },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ listByChannel (options: OverrideCommandOptions & VideosWithSearchCommonQuery & {
+ handle: string
+ }) {
+ const { handle } = options
+ const path = '/api/v1/video-channels/' + handle + '/videos'
+
+ return this.getRequestBody<ResultList<Video>>({
+ ...options,
+
+ path,
+ query: this.buildListQuery(options),
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ async find (options: OverrideCommandOptions & {
+ name: string
+ }) {
+ const { data } = await this.list(options)
+
+ return data.find(v => v.name === options.name)
+ }
+
+ // ---------------------------------------------------------------------------
+
+ update (options: OverrideCommandOptions & {
+ id: number | string
+ attributes?: VideoEdit
+ }) {
+ const { id, attributes = {} } = options
+ const path = '/api/v1/videos/' + id
+
+ // Upload request
+ if (attributes.thumbnailfile || attributes.previewfile) {
+ const attaches: any = {}
+ if (attributes.thumbnailfile) attaches.thumbnailfile = attributes.thumbnailfile
+ if (attributes.previewfile) attaches.previewfile = attributes.previewfile
+
+ return this.putUploadRequest({
+ ...options,
+
+ path,
+ fields: options.attributes,
+ attaches: {
+ thumbnailfile: attributes.thumbnailfile,
+ previewfile: attributes.previewfile
+ },
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ return this.putBodyRequest({
+ ...options,
+
+ path,
+ fields: options.attributes,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ })
+ }
+
+ remove (options: OverrideCommandOptions & {
+ id: number | string
+ }) {
+ const path = '/api/v1/videos/' + options.id
+
+ return unwrapBody(this.deleteRequest({
+ ...options,
+
+ path,
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
+ }))
+ }
+
+ async removeAll () {
+ const { data } = await this.list()
+
+ for (const v of data) {
+ await this.remove({ id: v.id })
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ async upload (options: OverrideCommandOptions & {
+ attributes?: VideoEdit
+ mode?: 'legacy' | 'resumable' // default legacy
+ } = {}) {
+ const { mode = 'legacy' } = options
+ let defaultChannelId = 1
+
+ try {
+ const { videoChannels } = await this.server.users.getMyInfo({ token: options.token })
+ defaultChannelId = videoChannels[0].id
+ } catch (e) { /* empty */ }
+
+ // Override default attributes
+ const attributes = {
+ name: 'my super video',
+ category: 5,
+ licence: 4,
+ language: 'zh',
+ channelId: defaultChannelId,
+ nsfw: true,
+ waitTranscoding: false,
+ description: 'my super description',
+ support: 'my super support text',
+ tags: [ 'tag' ],
+ privacy: VideoPrivacy.PUBLIC,
+ commentsEnabled: true,
+ downloadEnabled: true,
+ fixture: 'video_short.webm',
+
+ ...options.attributes
+ }
+
+ const created = mode === 'legacy'
+ ? await this.buildLegacyUpload({ ...options, attributes })
+ : await this.buildResumeUpload({ ...options, attributes })
+
+ // Wait torrent generation
+ const expectedStatus = this.buildExpectedStatus({ ...options, defaultExpectedStatus: HttpStatusCode.OK_200 })
+ if (expectedStatus === HttpStatusCode.OK_200) {
+ let video: VideoDetails
+
+ do {
+ video = await this.getWithToken({ ...options, id: created.uuid })
+
+ await wait(50)
+ } while (!video.files[0].torrentUrl)
+ }
+
+ return created
+ }
+
+ async buildLegacyUpload (options: OverrideCommandOptions & {
+ attributes: VideoEdit
+ }): Promise<VideoCreateResult> {
+ const path = '/api/v1/videos/upload'
+
+ return unwrapBody<{ video: VideoCreateResult }>(this.postUploadRequest({
+ ...options,
+
+ path,
+ fields: this.buildUploadFields(options.attributes),
+ attaches: this.buildUploadAttaches(options.attributes),
+ implicitToken: true,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })).then(body => body.video || body as any)
+ }
+
+ async buildResumeUpload (options: OverrideCommandOptions & {
+ attributes: VideoEdit
+ }): Promise<VideoCreateResult> {
+ const { attributes, expectedStatus } = options
+
+ let size = 0
+ let videoFilePath: string
+ let mimetype = 'video/mp4'
+
+ if (attributes.fixture) {
+ videoFilePath = buildAbsoluteFixturePath(attributes.fixture)
+ size = (await stat(videoFilePath)).size
+
+ if (videoFilePath.endsWith('.mkv')) {
+ mimetype = 'video/x-matroska'
+ } else if (videoFilePath.endsWith('.webm')) {
+ mimetype = 'video/webm'
+ }
+ }
+
+ // Do not check status automatically, we'll check it manually
+ const initializeSessionRes = await this.prepareResumableUpload({ ...options, expectedStatus: null, attributes, size, mimetype })
+ const initStatus = initializeSessionRes.status
+
+ if (videoFilePath && initStatus === HttpStatusCode.CREATED_201) {
+ const locationHeader = initializeSessionRes.header['location']
+ expect(locationHeader).to.not.be.undefined
+
+ const pathUploadId = locationHeader.split('?')[1]
+
+ const result = await this.sendResumableChunks({ ...options, pathUploadId, videoFilePath, size })
+
+ return result.body?.video || result.body as any
+ }
+
+ const expectedInitStatus = expectedStatus === HttpStatusCode.OK_200
+ ? HttpStatusCode.CREATED_201
+ : expectedStatus
+
+ expect(initStatus).to.equal(expectedInitStatus)
+
+ return initializeSessionRes.body.video || initializeSessionRes.body
+ }
+
+ async prepareResumableUpload (options: OverrideCommandOptions & {
+ attributes: VideoEdit
+ size: number
+ mimetype: string
+ }) {
+ const { attributes, size, mimetype } = options
+
+ const path = '/api/v1/videos/upload-resumable'
+
+ return this.postUploadRequest({
+ ...options,
+
+ path,
+ headers: {
+ 'X-Upload-Content-Type': mimetype,
+ 'X-Upload-Content-Length': size.toString()
+ },
+ fields: { filename: attributes.fixture, ...this.buildUploadFields(options.attributes) },
+ // Fixture will be sent later
+ attaches: this.buildUploadAttaches(omit(options.attributes, 'fixture')),
+ implicitToken: true,
+
+ defaultExpectedStatus: null
+ })
+ }
+
+ sendResumableChunks (options: OverrideCommandOptions & {
+ pathUploadId: string
+ videoFilePath: string
+ size: number
+ contentLength?: number
+ contentRangeBuilder?: (start: number, chunk: any) => string
+ }) {
+ const { pathUploadId, videoFilePath, size, contentLength, contentRangeBuilder, expectedStatus = HttpStatusCode.OK_200 } = options
+
+ const path = '/api/v1/videos/upload-resumable'
+ let start = 0
+
+ const token = this.buildCommonRequestToken({ ...options, implicitToken: true })
+ const url = this.server.url
+
+ const readable = createReadStream(videoFilePath, { highWaterMark: 8 * 1024 })
+ return new Promise<GotResponse<{ video: VideoCreateResult }>>((resolve, reject) => {
+ readable.on('data', async function onData (chunk) {
+ readable.pause()
+
+ const headers = {
+ 'Authorization': 'Bearer ' + token,
+ 'Content-Type': 'application/octet-stream',
+ 'Content-Range': contentRangeBuilder
+ ? contentRangeBuilder(start, chunk)
+ : `bytes ${start}-${start + chunk.length - 1}/${size}`,
+ 'Content-Length': contentLength ? contentLength + '' : chunk.length + ''
+ }
+
+ const res = await got<{ video: VideoCreateResult }>({
+ url,
+ method: 'put',
+ headers,
+ path: path + '?' + pathUploadId,
+ body: chunk,
+ responseType: 'json',
+ throwHttpErrors: false
+ })
+
+ start += chunk.length
+
+ if (res.statusCode === expectedStatus) {
+ return resolve(res)
+ }
+
+ if (res.statusCode !== HttpStatusCode.PERMANENT_REDIRECT_308) {
+ readable.off('data', onData)
+ return reject(new Error('Incorrect transient behaviour sending intermediary chunks'))
+ }
+
+ readable.resume()
+ })
+ })
+ }
+
+ quickUpload (options: OverrideCommandOptions & {
+ name: string
+ nsfw?: boolean
+ privacy?: VideoPrivacy
+ fixture?: string
+ }) {
+ const attributes: VideoEdit = { name: options.name }
+ if (options.nsfw) attributes.nsfw = options.nsfw
+ if (options.privacy) attributes.privacy = options.privacy
+ if (options.fixture) attributes.fixture = options.fixture
+
+ return this.upload({ ...options, attributes })
+ }
+
+ async randomUpload (options: OverrideCommandOptions & {
+ wait?: boolean // default true
+ additionalParams?: VideoEdit & { prefixName?: string }
+ } = {}) {
+ const { wait = true, additionalParams } = options
+ const prefixName = additionalParams?.prefixName || ''
+ const name = prefixName + buildUUID()
+
+ const attributes = { name, ...additionalParams }
+
+ const result = await this.upload({ ...options, attributes })
+
+ if (wait) await waitJobs([ this.server ])
+
+ return { ...result, name }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ private buildListQuery (options: VideosCommonQuery) {
+ return pick(options, [
+ 'start',
+ 'count',
+ 'sort',
+ 'nsfw',
+ 'isLive',
+ 'categoryOneOf',
+ 'licenceOneOf',
+ 'languageOneOf',
+ 'tagsOneOf',
+ 'tagsAllOf',
+ 'filter',
+ 'skipCount'
+ ])
+ }
+
+ private buildUploadFields (attributes: VideoEdit) {
+ return omit(attributes, [ 'fixture', 'thumbnailfile', 'previewfile' ])
+ }
+
+ private buildUploadAttaches (attributes: VideoEdit) {
+ const attaches: { [ name: string ]: string } = {}
+
+ for (const key of [ 'thumbnailfile', 'previewfile' ]) {
+ if (attributes[key]) attaches[key] = buildAbsoluteFixturePath(attributes[key])
+ }
+
+ if (attributes.fixture) attaches.videofile = buildAbsoluteFixturePath(attributes.fixture)
+
+ return attaches
+ }
+}
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
import { expect } from 'chai'
-import { createReadStream, pathExists, readdir, readFile, stat } from 'fs-extra'
-import got, { Response as GotResponse } from 'got/dist/source'
-import * as parseTorrent from 'parse-torrent'
-import { join } from 'path'
-import * as request from 'supertest'
-import validator from 'validator'
+import { pathExists, readdir } from 'fs-extra'
+import { basename, join } from 'path'
import { getLowercaseExtension } from '@server/helpers/core-utils'
-import { buildUUID } from '@server/helpers/uuid'
-import { HttpStatusCode } from '@shared/core-utils'
-import { VideosCommonQuery } from '@shared/models'
-import { loadLanguages, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants'
-import { VideoDetails, VideoPrivacy } from '../../models/videos'
-import {
- buildAbsoluteFixturePath,
- buildServerDirectory,
- dateIsValid,
- immutableAssign,
- testImage,
- wait,
- webtorrentAdd
-} from '../miscs/miscs'
-import { makeGetRequest, makePutBodyRequest, makeRawRequest, makeUploadRequest } from '../requests/requests'
-import { waitJobs } from '../server/jobs'
-import { ServerInfo } from '../server/servers'
-import { getMyUserInformation } from '../users/users'
-
-loadLanguages()
-
-type VideoAttributes = {
- name?: string
- category?: number
- licence?: number
- language?: string
- nsfw?: boolean
- commentsEnabled?: boolean
- downloadEnabled?: boolean
- waitTranscoding?: boolean
- description?: string
- originallyPublishedAt?: string
- tags?: string[]
- channelId?: number
- privacy?: VideoPrivacy
- fixture?: string
- support?: string
- thumbnailfile?: string
- previewfile?: string
- scheduleUpdate?: {
- updateAt: string
- privacy?: VideoPrivacy
- }
-}
-
-function getVideoCategories (url: string) {
- const path = '/api/v1/videos/categories'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoLicences (url: string) {
- const path = '/api/v1/videos/licences'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoLanguages (url: string) {
- const path = '/api/v1/videos/languages'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoPrivacies (url: string) {
- const path = '/api/v1/videos/privacies'
-
- return makeGetRequest({
- url,
- path,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideo (url: string, id: number | string, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/videos/' + id
-
- return request(url)
- .get(path)
- .set('Accept', 'application/json')
- .expect(expectedStatus)
-}
+import { uuidRegex } from '@shared/core-utils'
+import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models'
+import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants'
+import { dateIsValid, testImage, webtorrentAdd } from '../miscs'
+import { makeRawRequest } from '../requests/requests'
+import { waitJobs } from '../server'
+import { PeerTubeServer } from '../server/server'
+import { VideoEdit } from './videos-command'
+
+async function checkVideoFilesWereRemoved (options: {
+ server: PeerTubeServer
+ video: VideoDetails
+ captions?: VideoCaption[]
+ onlyVideoFiles?: boolean // default false
+}) {
+ const { video, server, captions = [], onlyVideoFiles = false } = options
-async function getVideoIdFromUUID (url: string, uuid: string) {
- const res = await getVideo(url, uuid)
+ const webtorrentFiles = video.files || []
+ const hlsFiles = video.streamingPlaylists[0]?.files || []
- return res.body.id
-}
+ const thumbnailName = basename(video.thumbnailPath)
+ const previewName = basename(video.previewPath)
-function getVideoFileMetadataUrl (url: string) {
- return request(url)
- .get('/')
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
+ const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
-function viewVideo (url: string, id: number | string, expectedStatus = HttpStatusCode.NO_CONTENT_204, xForwardedFor?: string) {
- const path = '/api/v1/videos/' + id + '/views'
+ const captionNames = captions.map(c => basename(c.captionPath))
- const req = request(url)
- .post(path)
- .set('Accept', 'application/json')
+ const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl))
+ const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
- if (xForwardedFor) {
- req.set('X-Forwarded-For', xForwardedFor)
+ let directories: { [ directory: string ]: string[] } = {
+ videos: webtorrentFilenames,
+ redundancy: webtorrentFilenames,
+ [join('playlists', 'hls')]: hlsFilenames,
+ [join('redundancy', 'hls')]: hlsFilenames
}
- return req.expect(expectedStatus)
-}
-
-function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/videos/' + id
-
- return request(url)
- .get(path)
- .set('Authorization', 'Bearer ' + token)
- .set('Accept', 'application/json')
- .expect(expectedStatus)
-}
-
-function getVideoDescription (url: string, descriptionPath: string) {
- return request(url)
- .get(descriptionPath)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getVideosList (url: string) {
- const path = '/api/v1/videos'
-
- return request(url)
- .get(path)
- .query({ sort: 'name' })
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getVideosListWithToken (url: string, token: string, query: { nsfw?: boolean } = {}) {
- const path = '/api/v1/videos'
-
- return request(url)
- .get(path)
- .set('Authorization', 'Bearer ' + token)
- .query(immutableAssign(query, { sort: 'name' }))
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getLocalVideos (url: string) {
- const path = '/api/v1/videos'
-
- return request(url)
- .get(path)
- .query({ sort: 'name', filter: 'local' })
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string, search?: string) {
- const path = '/api/v1/users/me/videos'
-
- const req = request(url)
- .get(path)
- .query({ start: start })
- .query({ count: count })
- .query({ search: search })
-
- if (sort) req.query({ sort })
-
- return req.set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getMyVideosWithFilter (url: string, accessToken: string, query: { isLive?: boolean }) {
- const path = '/api/v1/users/me/videos'
-
- return makeGetRequest({
- url,
- path,
- token: accessToken,
- query,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getAccountVideos (
- url: string,
- accessToken: string,
- accountName: string,
- start: number,
- count: number,
- sort?: string,
- query: {
- nsfw?: boolean
- search?: string
- } = {}
-) {
- const path = '/api/v1/accounts/' + accountName + '/videos'
-
- return makeGetRequest({
- url,
- path,
- query: immutableAssign(query, {
- start,
- count,
- sort
- }),
- token: accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideoChannelVideos (
- url: string,
- accessToken: string,
- videoChannelName: string,
- start: number,
- count: number,
- sort?: string,
- query: { nsfw?: boolean } = {}
-) {
- const path = '/api/v1/video-channels/' + videoChannelName + '/videos'
-
- return makeGetRequest({
- url,
- path,
- query: immutableAssign(query, {
- start,
- count,
- sort
- }),
- token: accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getPlaylistVideos (
- url: string,
- accessToken: string,
- playlistId: number | string,
- start: number,
- count: number,
- query: { nsfw?: boolean } = {}
-) {
- const path = '/api/v1/video-playlists/' + playlistId + '/videos'
-
- return makeGetRequest({
- url,
- path,
- query: immutableAssign(query, {
- start,
- count
- }),
- token: accessToken,
- statusCodeExpected: HttpStatusCode.OK_200
- })
-}
-
-function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) {
- const path = '/api/v1/videos'
-
- const req = request(url)
- .get(path)
- .query({ start: start })
- .query({ count: count })
-
- if (sort) req.query({ sort })
- if (skipCount) req.query({ skipCount })
-
- return req.set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getVideosListSort (url: string, sort: string) {
- const path = '/api/v1/videos'
-
- return request(url)
- .get(path)
- .query({ sort: sort })
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function getVideosWithFilters (url: string, query: VideosCommonQuery) {
- const path = '/api/v1/videos'
-
- return request(url)
- .get(path)
- .query(query)
- .set('Accept', 'application/json')
- .expect(HttpStatusCode.OK_200)
- .expect('Content-Type', /json/)
-}
-
-function removeVideo (url: string, token: string, id: number | string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/videos'
-
- return request(url)
- .delete(path + '/' + id)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(expectedStatus)
-}
+ if (onlyVideoFiles !== true) {
+ directories = {
+ ...directories,
-async function removeAllVideos (server: ServerInfo) {
- const resVideos = await getVideosList(server.url)
-
- for (const v of resVideos.body.data) {
- await removeVideo(server.url, server.accessToken, v.id)
+ thumbnails: [ thumbnailName ],
+ previews: [ previewName ],
+ torrents: torrentNames,
+ captions: captionNames
+ }
}
-}
-async function checkVideoFilesWereRemoved (
- videoUUID: string,
- serverNumber: number,
- directories = [
- 'redundancy',
- 'videos',
- 'thumbnails',
- 'torrents',
- 'previews',
- 'captions',
- join('playlists', 'hls'),
- join('redundancy', 'hls')
- ]
-) {
- for (const directory of directories) {
- const directoryPath = buildServerDirectory({ internalServerNumber: serverNumber }, directory)
+ for (const directory of Object.keys(directories)) {
+ const directoryPath = server.servers.buildDirectory(directory)
const directoryExists = await pathExists(directoryPath)
if (directoryExists === false) continue
- const files = await readdir(directoryPath)
- for (const file of files) {
- expect(file, `File ${file} should not exist in ${directoryPath}`).to.not.contain(videoUUID)
+ const existingFiles = await readdir(directoryPath)
+ for (const existingFile of existingFiles) {
+ for (const shouldNotExist of directories[directory]) {
+ expect(existingFile, `File ${existingFile} should not exist in ${directoryPath}`).to.not.contain(shouldNotExist)
+ }
}
}
}
-async function uploadVideo (
- url: string,
- accessToken: string,
- videoAttributesArg: VideoAttributes,
- specialStatus = HttpStatusCode.OK_200,
- mode: 'legacy' | 'resumable' = 'legacy'
-) {
- let defaultChannelId = '1'
-
- try {
- const res = await getMyUserInformation(url, accessToken)
- defaultChannelId = res.body.videoChannels[0].id
- } catch (e) { /* empty */ }
-
- // Override default attributes
- const attributes = Object.assign({
- name: 'my super video',
- category: 5,
- licence: 4,
- language: 'zh',
- channelId: defaultChannelId,
- nsfw: true,
- waitTranscoding: false,
- description: 'my super description',
- support: 'my super support text',
- tags: [ 'tag' ],
- privacy: VideoPrivacy.PUBLIC,
- commentsEnabled: true,
- downloadEnabled: true,
- fixture: 'video_short.webm'
- }, videoAttributesArg)
-
- const res = mode === 'legacy'
- ? await buildLegacyUpload(url, accessToken, attributes, specialStatus)
- : await buildResumeUpload(url, accessToken, attributes, specialStatus)
-
- // Wait torrent generation
- if (specialStatus === HttpStatusCode.OK_200) {
- let video: VideoDetails
- do {
- const resVideo = await getVideoWithToken(url, accessToken, res.body.video.uuid)
- video = resVideo.body
-
- await wait(50)
- } while (!video.files[0].torrentUrl)
+async function saveVideoInServers (servers: PeerTubeServer[], uuid: string) {
+ for (const server of servers) {
+ server.store.videoDetails = await server.videos.get({ id: uuid })
}
-
- return res
}
function checkUploadVideoParam (
- url: string,
+ server: PeerTubeServer,
token: string,
- attributes: Partial<VideoAttributes>,
- specialStatus = HttpStatusCode.OK_200,
+ attributes: Partial<VideoEdit>,
+ expectedStatus = HttpStatusCode.OK_200,
mode: 'legacy' | 'resumable' = 'legacy'
) {
return mode === 'legacy'
- ? buildLegacyUpload(url, token, attributes, specialStatus)
- : buildResumeUpload(url, token, attributes, specialStatus)
-}
-
-async function buildLegacyUpload (url: string, token: string, attributes: VideoAttributes, specialStatus = HttpStatusCode.OK_200) {
- const path = '/api/v1/videos/upload'
- const req = request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
-
- buildUploadReq(req, attributes)
-
- if (attributes.fixture !== undefined) {
- req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture))
- }
-
- return req.expect(specialStatus)
-}
-
-async function buildResumeUpload (url: string, token: string, attributes: VideoAttributes, specialStatus = HttpStatusCode.OK_200) {
- let size = 0
- let videoFilePath: string
- let mimetype = 'video/mp4'
-
- if (attributes.fixture) {
- videoFilePath = buildAbsoluteFixturePath(attributes.fixture)
- size = (await stat(videoFilePath)).size
-
- if (videoFilePath.endsWith('.mkv')) {
- mimetype = 'video/x-matroska'
- } else if (videoFilePath.endsWith('.webm')) {
- mimetype = 'video/webm'
- }
- }
-
- const initializeSessionRes = await prepareResumableUpload({ url, token, attributes, size, mimetype })
- const initStatus = initializeSessionRes.status
-
- if (videoFilePath && initStatus === HttpStatusCode.CREATED_201) {
- const locationHeader = initializeSessionRes.header['location']
- expect(locationHeader).to.not.be.undefined
-
- const pathUploadId = locationHeader.split('?')[1]
-
- return sendResumableChunks({ url, token, pathUploadId, videoFilePath, size, specialStatus })
- }
-
- const expectedInitStatus = specialStatus === HttpStatusCode.OK_200
- ? HttpStatusCode.CREATED_201
- : specialStatus
-
- expect(initStatus).to.equal(expectedInitStatus)
-
- return initializeSessionRes
-}
-
-async function prepareResumableUpload (options: {
- url: string
- token: string
- attributes: VideoAttributes
- size: number
- mimetype: string
-}) {
- const { url, token, attributes, size, mimetype } = options
-
- const path = '/api/v1/videos/upload-resumable'
-
- const req = request(url)
- .post(path)
- .set('Authorization', 'Bearer ' + token)
- .set('X-Upload-Content-Type', mimetype)
- .set('X-Upload-Content-Length', size.toString())
-
- buildUploadReq(req, attributes)
-
- if (attributes.fixture) {
- req.field('filename', attributes.fixture)
- }
-
- return req
-}
-
-function sendResumableChunks (options: {
- url: string
- token: string
- pathUploadId: string
- videoFilePath: string
- size: number
- specialStatus?: HttpStatusCode
- contentLength?: number
- contentRangeBuilder?: (start: number, chunk: any) => string
-}) {
- const { url, token, pathUploadId, videoFilePath, size, specialStatus, contentLength, contentRangeBuilder } = options
-
- const expectedStatus = specialStatus || HttpStatusCode.OK_200
-
- const path = '/api/v1/videos/upload-resumable'
- let start = 0
-
- const readable = createReadStream(videoFilePath, { highWaterMark: 8 * 1024 })
- return new Promise<GotResponse>((resolve, reject) => {
- readable.on('data', async function onData (chunk) {
- readable.pause()
-
- const headers = {
- 'Authorization': 'Bearer ' + token,
- 'Content-Type': 'application/octet-stream',
- 'Content-Range': contentRangeBuilder
- ? contentRangeBuilder(start, chunk)
- : `bytes ${start}-${start + chunk.length - 1}/${size}`,
- 'Content-Length': contentLength ? contentLength + '' : chunk.length + ''
- }
-
- const res = await got({
- url,
- method: 'put',
- headers,
- path: path + '?' + pathUploadId,
- body: chunk,
- responseType: 'json',
- throwHttpErrors: false
- })
-
- start += chunk.length
-
- if (res.statusCode === expectedStatus) {
- return resolve(res)
- }
-
- if (res.statusCode !== HttpStatusCode.PERMANENT_REDIRECT_308) {
- readable.off('data', onData)
- return reject(new Error('Incorrect transient behaviour sending intermediary chunks'))
- }
-
- readable.resume()
- })
- })
-}
-
-function updateVideo (
- url: string,
- accessToken: string,
- id: number | string,
- attributes: VideoAttributes,
- statusCodeExpected = HttpStatusCode.NO_CONTENT_204
-) {
- const path = '/api/v1/videos/' + id
- const body = {}
-
- if (attributes.name) body['name'] = attributes.name
- if (attributes.category) body['category'] = attributes.category
- if (attributes.licence) body['licence'] = attributes.licence
- if (attributes.language) body['language'] = attributes.language
- if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw)
- if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled)
- if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled)
- if (attributes.originallyPublishedAt !== undefined) body['originallyPublishedAt'] = attributes.originallyPublishedAt
- if (attributes.description) body['description'] = attributes.description
- if (attributes.tags) body['tags'] = attributes.tags
- if (attributes.privacy) body['privacy'] = attributes.privacy
- if (attributes.channelId) body['channelId'] = attributes.channelId
- if (attributes.scheduleUpdate) body['scheduleUpdate'] = attributes.scheduleUpdate
-
- // Upload request
- if (attributes.thumbnailfile || attributes.previewfile) {
- const attaches: any = {}
- if (attributes.thumbnailfile) attaches.thumbnailfile = attributes.thumbnailfile
- if (attributes.previewfile) attaches.previewfile = attributes.previewfile
-
- return makeUploadRequest({
- url,
- method: 'PUT',
- path,
- token: accessToken,
- fields: body,
- attaches,
- statusCodeExpected
- })
- }
-
- return makePutBodyRequest({
- url,
- path,
- fields: body,
- token: accessToken,
- statusCodeExpected
- })
-}
-
-function rateVideo (url: string, accessToken: string, id: number | string, rating: string, specialStatus = HttpStatusCode.NO_CONTENT_204) {
- const path = '/api/v1/videos/' + id + '/rate'
-
- return request(url)
- .put(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + accessToken)
- .send({ rating })
- .expect(specialStatus)
-}
-
-function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
- return new Promise<any>((res, rej) => {
- const torrentName = videoUUID + '-' + resolution + '.torrent'
- const torrentPath = buildServerDirectory(server, join('torrents', torrentName))
-
- readFile(torrentPath, (err, data) => {
- if (err) return rej(err)
-
- return res(parseTorrent(data))
- })
- })
+ ? server.videos.buildLegacyUpload({ token, attributes, expectedStatus })
+ : server.videos.buildResumeUpload({ token, attributes, expectedStatus })
}
async function completeVideoCheck (
- url: string,
+ server: PeerTubeServer,
video: any,
attributes: {
name: string
if (!attributes.likes) attributes.likes = 0
if (!attributes.dislikes) attributes.dislikes = 0
- const host = new URL(url).host
+ const host = new URL(server.url).host
const originHost = attributes.account.host
expect(video.name).to.equal(attributes.name)
expect(video.originallyPublishedAt).to.be.null
}
- const res = await getVideo(url, video.uuid)
- const videoDetails: VideoDetails = res.body
+ const videoDetails = await server.videos.get({ id: video.uuid })
expect(videoDetails.files).to.have.lengthOf(attributes.files.length)
expect(videoDetails.tags).to.deep.equal(attributes.tags)
expect(file.magnetUri).to.have.lengthOf.above(2)
- expect(file.torrentDownloadUrl).to.equal(`http://${host}/download/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`)
- expect(file.torrentUrl).to.equal(`http://${host}/lazy-static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`)
+ expect(file.torrentDownloadUrl).to.match(new RegExp(`http://${host}/download/torrents/${uuidRegex}-${file.resolution.id}.torrent`))
+ expect(file.torrentUrl).to.match(new RegExp(`http://${host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}.torrent`))
- expect(file.fileUrl).to.equal(`http://${originHost}/static/webseed/${videoDetails.uuid}-${file.resolution.id}${extension}`)
- expect(file.fileDownloadUrl).to.equal(`http://${originHost}/download/videos/${videoDetails.uuid}-${file.resolution.id}${extension}`)
+ expect(file.fileUrl).to.match(new RegExp(`http://${originHost}/static/webseed/${uuidRegex}-${file.resolution.id}${extension}`))
+ expect(file.fileDownloadUrl).to.match(new RegExp(`http://${originHost}/download/videos/${uuidRegex}-${file.resolution.id}${extension}`))
await Promise.all([
makeRawRequest(file.torrentUrl, 200),
makeRawRequest(file.torrentDownloadUrl, 200),
- makeRawRequest(file.metadataUrl, 200),
- // Backward compatibility
- makeRawRequest(`http://${originHost}/static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`, 200)
+ makeRawRequest(file.metadataUrl, 200)
])
expect(file.resolution.id).to.equal(attributeFile.resolution)
}
expect(videoDetails.thumbnailPath).to.exist
- await testImage(url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath)
+ await testImage(server.url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath)
if (attributes.previewfile) {
expect(videoDetails.previewPath).to.exist
- await testImage(url, attributes.previewfile, videoDetails.previewPath)
+ await testImage(server.url, attributes.previewfile, videoDetails.previewPath)
}
}
-async function videoUUIDToId (url: string, id: number | string) {
- if (validator.isUUID('' + id) === false) return id
-
- const res = await getVideo(url, id)
- return res.body.id
-}
-
-async function uploadVideoAndGetId (options: {
- server: ServerInfo
- videoName: string
- nsfw?: boolean
- privacy?: VideoPrivacy
- token?: string
- fixture?: string
-}) {
- const videoAttrs: any = { name: options.videoName }
- if (options.nsfw) videoAttrs.nsfw = options.nsfw
- if (options.privacy) videoAttrs.privacy = options.privacy
- if (options.fixture) videoAttrs.fixture = options.fixture
-
- const res = await uploadVideo(options.server.url, options.token || options.server.accessToken, videoAttrs)
-
- return res.body.video as { id: number, uuid: string, shortUUID: string }
-}
-
-async function getLocalIdByUUID (url: string, uuid: string) {
- const res = await getVideo(url, uuid)
-
- return res.body.id
-}
-
// serverNumber starts from 1
-async function uploadRandomVideoOnServers (servers: ServerInfo[], serverNumber: number, additionalParams: any = {}) {
+async function uploadRandomVideoOnServers (
+ servers: PeerTubeServer[],
+ serverNumber: number,
+ additionalParams?: VideoEdit & { prefixName?: string }
+) {
const server = servers.find(s => s.serverNumber === serverNumber)
- const res = await uploadRandomVideo(server, false, additionalParams)
+ const res = await server.videos.randomUpload({ wait: false, additionalParams })
await waitJobs(servers)
return res
}
-async function uploadRandomVideo (server: ServerInfo, wait = true, additionalParams: any = {}) {
- const prefixName = additionalParams.prefixName || ''
- const name = prefixName + buildUUID()
-
- const data = Object.assign({ name }, additionalParams)
- const res = await uploadVideo(server.url, server.accessToken, data)
-
- if (wait) await waitJobs([ server ])
-
- return { uuid: res.body.video.uuid, name }
-}
-
// ---------------------------------------------------------------------------
export {
- getVideoDescription,
- getVideoCategories,
- uploadRandomVideo,
- getVideoLicences,
- videoUUIDToId,
- getVideoPrivacies,
- getVideoLanguages,
- getMyVideos,
- getAccountVideos,
- getVideoChannelVideos,
- getVideo,
- getVideoFileMetadataUrl,
- getVideoWithToken,
- getVideosList,
- removeAllVideos,
checkUploadVideoParam,
- getVideosListPagination,
- getVideosListSort,
- removeVideo,
- getVideosListWithToken,
- uploadVideo,
- sendResumableChunks,
- getVideosWithFilters,
- uploadRandomVideoOnServers,
- updateVideo,
- rateVideo,
- viewVideo,
- parseTorrentVideo,
- getLocalVideos,
completeVideoCheck,
+ uploadRandomVideoOnServers,
checkVideoFilesWereRemoved,
- getPlaylistVideos,
- getMyVideosWithFilter,
- uploadVideoAndGetId,
- getLocalIdByUUID,
- getVideoIdFromUUID,
- prepareResumableUpload
-}
-
-// ---------------------------------------------------------------------------
-
-function buildUploadReq (req: request.Test, attributes: VideoAttributes) {
-
- for (const key of [ 'name', 'support', 'channelId', 'description', 'originallyPublishedAt' ]) {
- if (attributes[key] !== undefined) {
- req.field(key, attributes[key])
- }
- }
-
- for (const key of [ 'nsfw', 'commentsEnabled', 'downloadEnabled', 'waitTranscoding' ]) {
- if (attributes[key] !== undefined) {
- req.field(key, JSON.stringify(attributes[key]))
- }
- }
-
- for (const key of [ 'language', 'privacy', 'category', 'licence' ]) {
- if (attributes[key] !== undefined) {
- req.field(key, attributes[key].toString())
- }
- }
-
- const tags = attributes.tags || []
- for (let i = 0; i < tags.length; i++) {
- req.field('tags[' + i + ']', attributes.tags[i])
- }
-
- for (const key of [ 'thumbnailfile', 'previewfile' ]) {
- if (attributes[key] !== undefined) {
- req.attach(key, buildAbsoluteFixturePath(attributes[key]))
- }
- }
-
- if (attributes.scheduleUpdate) {
- if (attributes.scheduleUpdate.updateAt) {
- req.field('scheduleUpdate[updateAt]', attributes.scheduleUpdate.updateAt)
- }
-
- if (attributes.scheduleUpdate.privacy) {
- req.field('scheduleUpdate[privacy]', attributes.scheduleUpdate.privacy)
- }
- }
+ saveVideoInServers
}
--- /dev/null
+export * from './http-error-codes'
+export * from './http-methods'
export * from './common'
export * from './custom-markup'
export * from './feeds'
+export * from './http'
export * from './joinpeertube'
export * from './moderation'
export * from './overviews'
import { VideoPlaylistPrivacy } from '../../../videos/playlist/video-playlist-privacy.model'
+import { ConstantManager } from '../plugin-constant-manager.model'
-export interface PluginPlaylistPrivacyManager {
- // PUBLIC = 1,
- // UNLISTED = 2,
- // PRIVATE = 3
+export interface PluginPlaylistPrivacyManager extends ConstantManager<VideoPlaylistPrivacy> {
+ /**
+ * PUBLIC = 1,
+ * UNLISTED = 2,
+ * PRIVATE = 3
+ * @deprecated use `deleteConstant` instead
+ */
deletePlaylistPrivacy: (privacyKey: VideoPlaylistPrivacy) => boolean
}
-export interface PluginVideoCategoryManager {
+import { ConstantManager } from '../plugin-constant-manager.model'
+
+export interface PluginVideoCategoryManager extends ConstantManager<number> {
+ /**
+ * @deprecated use `addConstant` instead
+ */
addCategory: (categoryKey: number, categoryLabel: string) => boolean
+ /**
+ * @deprecated use `deleteConstant` instead
+ */
deleteCategory: (categoryKey: number) => boolean
}
-export interface PluginVideoLanguageManager {
+import { ConstantManager } from '../plugin-constant-manager.model'
+
+export interface PluginVideoLanguageManager extends ConstantManager<string> {
+ /**
+ * @deprecated use `addConstant` instead
+ */
addLanguage: (languageKey: string, languageLabel: string) => boolean
+ /**
+ * @deprecated use `deleteConstant` instead
+ */
deleteLanguage: (languageKey: string) => boolean
}
-export interface PluginVideoLicenceManager {
+import { ConstantManager } from '../plugin-constant-manager.model'
+
+export interface PluginVideoLicenceManager extends ConstantManager<number> {
+ /**
+ * @deprecated use `addLicence` instead
+ */
addLicence: (licenceKey: number, licenceLabel: string) => boolean
+ /**
+ * @deprecated use `deleteLicence` instead
+ */
deleteLicence: (licenceKey: number) => boolean
}
import { VideoPrivacy } from '../../../videos/video-privacy.enum'
+import { ConstantManager } from '../plugin-constant-manager.model'
-export interface PluginVideoPrivacyManager {
- // PUBLIC = 1
- // UNLISTED = 2
- // PRIVATE = 3
- // INTERNAL = 4
+export interface PluginVideoPrivacyManager extends ConstantManager<VideoPrivacy> {
+ /**
+ * PUBLIC = 1,
+ * UNLISTED = 2,
+ * PRIVATE = 3
+ * INTERNAL = 4
+ * @deprecated use `deleteConstant` instead
+ */
deletePrivacy: (privacyKey: VideoPrivacy) => boolean
}
--- /dev/null
+export interface ConstantManager <K extends string | number> {
+ addConstant: (key: K, label: string) => boolean
+ deleteConstant: (key: K) => boolean
+ getConstantValue: (key: K) => string
+ getConstants: () => Record<K, string>
+ resetConstants: () => void
+}
'filter:api.user.me.videos.list.params': true,
'filter:api.user.me.videos.list.result': true,
+ // Filter params/result used to list overview videos for the REST API
+ 'filter:api.overviews.videos.list.params': true,
+ 'filter:api.overviews.videos.list.result': true,
+
// Filter params/results to search videos/channels in the DB or on the remote index
'filter:api.search.videos.local.list.params': true,
'filter:api.search.videos.local.list.result': true,
import { SearchTargetQuery } from './search-target-query.model'
export interface VideoChannelsSearchQuery extends SearchTargetQuery {
- search: string
+ search?: string
start?: number
count?: number
sort?: string
+
+ host?: string
+ handles?: string[]
+}
+
+export interface VideoChannelsSearchQueryAfterSanitize extends VideoChannelsSearchQuery {
+ start: number
+ count: number
+ sort: string
}
import { SearchTargetQuery } from './search-target-query.model'
export interface VideoPlaylistsSearchQuery extends SearchTargetQuery {
- search: string
+ search?: string
start?: number
count?: number
sort?: string
+
+ host?: string
+
+ // UUIDs or short UUIDs
+ uuids?: string[]
+}
+
+export interface VideoPlaylistsSearchQueryAfterSanitize extends VideoPlaylistsSearchQuery {
+ start: number
+ count: number
+ sort: string
}
tagsAllOf?: string[]
filter?: VideoFilter
+
+ skipCount?: boolean
+}
+
+export interface VideosCommonQueryAfterSanitize extends VideosCommonQuery {
+ start: number
+ count: number
+ sort: string
}
export interface VideosWithSearchCommonQuery extends VideosCommonQuery {
export interface VideosSearchQuery extends SearchTargetQuery, VideosCommonQuery {
search?: string
+ host?: string
+
startDate?: string // ISO 8601
endDate?: string // ISO 8601
durationMin?: number // seconds
durationMax?: number // seconds
+
+ // UUIDs or short UUIDs
+ uuids?: string[]
+}
+
+export interface VideosSearchQueryAfterSanitize extends VideosSearchQuery {
+ start: number
+ count: number
+ sort: string
}
export interface Debug {
ip: string
+ activityPubMessagesWaiting: number
}
export interface SendDebugCommand {
export * from './server-config.model'
export * from './server-debug.model'
export * from './server-error-code.enum'
+export * from './server-follow-create.model'
export * from './server-stats.model'
-import { HttpStatusCode } from '../../core-utils'
+import { HttpStatusCode } from '../../models'
import { OAuth2ErrorCode, ServerErrorCode } from './server-error-code.enum'
export interface PeerTubeProblemDocumentData {
--- /dev/null
+export interface ServerFollowCreate {
+ hosts?: string[]
+ handles?: string[]
+}
+export * from './user-create-result.model'
export * from './user-create.model'
export * from './user-flag.model'
export * from './user-login.model'
--- /dev/null
+export interface UserCreateResult {
+ id: number
+
+ account: {
+ id: number
+ }
+}
export interface VideoInfo {
id: number
uuid: string
+ shortUUID: string
name: string
}
comment?: {
threadId: number
- video: {
- id: number
- uuid: string
- name: string
- }
+ video: VideoInfo
}
account?: ActorInfo
+export * from './video-channel-create-result.model'
export * from './video-channel-create.model'
export * from './video-channel-update.model'
export * from './video-channel.model'
--- /dev/null
+export interface VideoChannelCreateResult {
+ id: number
+}
+export * from './video-comment-create.model'
export * from './video-comment.model'
--- /dev/null
+export interface VideoCommentCreate {
+ text: string
+}
+import { ResultList } from '../../common'
import { Account } from '../../actors'
export interface VideoComment {
}
}
+export type VideoCommentThreads = ResultList<VideoComment> & { totalNotDeletedComments: number }
+
export interface VideoCommentThreadTree {
comment: VideoComment
children: VideoCommentThreadTree[]
}
-
-export interface VideoCommentCreate {
- text: string
-}
export * from './video-exist-in-playlist.model'
export * from './video-playlist-create-result.model'
export * from './video-playlist-create.model'
+export * from './video-playlist-element-create-result.model'
export * from './video-playlist-element-create.model'
export * from './video-playlist-element-update.model'
export * from './video-playlist-element.model'
--- /dev/null
+export interface VideoPlaylistElementCreateResult {
+ id: number
+}
import { VideoPrivacy } from './video-privacy.enum'
import { VideoScheduleUpdate } from './video-schedule-update.model'
+
export interface VideoUpdate {
name?: string
category?: number
- admin
tags:
- Instance Follows
- summary: Follow a list of servers
+ summary: Follow a list of actors (PeerTube instance, channel or account)
responses:
'204':
description: successful operation
type: string
format: hostname
uniqueItems: true
+ handles:
+ type: array
+ items:
+ type: string
+ uniqueItems: true
- '/server/following/{host}':
+ '/server/following/{hostOrHandle}':
delete:
- summary: Unfollow a server
+ summary: Unfollow an actor (PeerTube instance, channel or account)
security:
- OAuth2:
- admin
tags:
- Instance Follows
parameters:
- - name: host
+ - name: hostOrHandle
in: path
required: true
- description: The host to unfollow
+ description: The hostOrHandle to unfollow
schema:
type: string
- format: hostname
responses:
'204':
description: successful operation
'404':
- description: host not found
+ description: host or handle not found
/users:
post:
sudo systemctl enable --now postgresql
```
+## Rocky Linux 8.4
+
+1. Pull the latest updates:
+```
+sudo dnf update -y
+```
+
+2. Install NodeJS 12.x (why 12 and not 14? Not sure...):
+```
+sudo dnf module install -y nodejs:12
+```
+
+3. Install yarn:
+```
+sudo npm install --global yarn
+```
+
+4. Install or compile ffmpeg (if you want to compile... enjoy):
+```
+sudo dnf install -y epel-release
+sudo dnf --enablerepo=powertools install -y SDL2 SDL2-devel
+sudo dnf install -y --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm
+sudo dnf install -y ffmpeg
+sudo dnf update -y
+```
+
+5. Install PostgreSQL and Python3 and other stuff:
+```
+sudo dnf install -y nginx postgresql postgresql-server postgresql-contrib openssl gcc-c++ make wget redis git python3
+sudo ln -s /usr/bin/python3 /usr/bin/python
+sudo PGSETUP_INITDB_OPTIONS='--auth-host=md5' postgresql-setup --initdb --unit postgresql
+sudo systemctl enable --now redis
+sudo systemctl enable --now postgresql
+```
+
+6. Configure the peertube user:
+```
+sudo useradd -m -d /var/www/peertube -s /bin/bash -p peertube peertube
+```
+
+7. Unknown missing steps:
+- Steps missing here... these were adapted from the CentOS 8 steps which abruptly ended.
+- /var/www/peertube does not exist yet (expected? done in future steps? documentation?).
+- Nothing about Certbot, NGINX, Firewall settings, and etc.
+- Hopefully someone can suggest what is missing here with some hints so I can add it?
## Fedora
#### Update video constants
-You can add/delete video categories, licences or languages using the appropriate managers:
+You can add/delete video categories, licences or languages using the appropriate constant managers:
```js
-function register (...) {
- videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
- videoLanguageManager.deleteLanguage('fr')
+function register ({
+ videoLanguageManager,
+ videoCategoryManager,
+ videoLicenceManager,
+ videoPrivacyManager,
+ playlistPrivacyManager
+}) {
+ videoLanguageManager.addConstant('al_bhed', 'Al Bhed')
+ videoLanguageManager.deleteConstant('fr')
- videoCategoryManager.addCategory(42, 'Best category')
- videoCategoryManager.deleteCategory(1) // Music
+ videoCategoryManager.addConstant(42, 'Best category')
+ videoCategoryManager.deleteConstant(1) // Music
+ videoCategoryManager.resetConstants() // Reset to initial categories
+ videoCategoryManager.getConstants() // Retrieve all category constants
- videoLicenceManager.addLicence(42, 'Best licence')
- videoLicenceManager.deleteLicence(7) // Public domain
+ videoLicenceManager.addConstant(42, 'Best licence')
+ videoLicenceManager.deleteConstant(7) // Public domain
- videoPrivacyManager.deletePrivacy(2) // Remove Unlisted video privacy
- playlistPrivacyManager.deletePlaylistPrivacy(3) // Remove Private video playlist privacy
+ videoPrivacyManager.deleteConstant(2) // Remove Unlisted video privacy
+ playlistPrivacyManager.deleteConstant(3) // Remove Private video playlist privacy
}
```
"emitDecoratorMetadata": true,
"importHelpers": true,
"removeComments": true,
+ "strictBindCallApply": true,
"outDir": "./dist",
"lib": [
"dom",
dependencies:
"@babel/highlight" "^7.14.5"
-"@babel/helper-validator-identifier@^7.14.5":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
- integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
+"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8":
+ version "7.14.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c"
+ integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==
"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5":
version "7.14.5"
js-tokens "^4.0.0"
"@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
- version "7.14.7"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595"
- integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==
+ version "7.14.8"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4"
+ integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==
"@babel/runtime@^7.7.2":
- version "7.14.6"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
- integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
+ version "7.14.8"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446"
+ integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/types@^7.6.1", "@babel/types@^7.9.6":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff"
- integrity sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==
+ version "7.14.8"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.8.tgz#38109de8fcadc06415fbd9b74df0065d4d41c728"
+ integrity sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q==
dependencies:
- "@babel/helper-validator-identifier" "^7.14.5"
+ "@babel/helper-validator-identifier" "^7.14.8"
to-fast-properties "^2.0.0"
"@dabh/diagnostics@^2.0.2":
kuler "^2.0.0"
"@digitalbazaar/http-client@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@digitalbazaar/http-client/-/http-client-1.1.0.tgz#cac383b24ace04b18b919deab773462b03d3d7b0"
- integrity sha512-ks7hqa6hm9NyULdbm9qL6TRS8rADzBw8R0lETvUgvdNXu9H62XG2YqoKRDThtfgWzWxLwRJ3Z2o4ev81dZZbyQ==
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@digitalbazaar/http-client/-/http-client-1.2.0.tgz#1ea3661e77000a15bd892a294f20dc6cc5d1c93b"
+ integrity sha512-W9KQQ5pUJcaR0I4c2HPJC0a7kRbZApIorZgPnEDwMBgj16iQzutGLrCXYaZOmxqVLVNqqlQ4aUJh+HBQZy4W6Q==
dependencies:
esm "^3.2.22"
ky "^0.25.1"
ky-universal "^0.8.2"
-"@eslint/eslintrc@^0.4.2":
- version "0.4.2"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"
- integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==
+"@eslint/eslintrc@^0.4.3":
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
+ integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
strip-json-comments "^3.1.1"
"@hapi/boom@^9.1.2":
- version "9.1.2"
- resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.2.tgz#48bd41d67437164a2d636e3b5bc954f8c8dc5e38"
- integrity sha512-uJEJtiNHzKw80JpngDGBCGAmWjBtzxDCz17A9NO2zCi8LLBlb5Frpq4pXwyN+2JQMod4pKz5BALwyneCgDg89Q==
+ version "9.1.3"
+ resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.3.tgz#22cad56e39b7a4819161a99b1db19eaaa9b6cc6e"
+ integrity sha512-RlrGyZ603hE/eRTZtTltocRm50HHmrmL3kGOP0SQ9MasazlW1mt/fkv4C5P/6rnpFXjwld/POFX1C8tMZE3ldg==
dependencies:
"@hapi/hoek" "9.x.x"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131"
integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==
+"@humanwhocodes/config-array@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
+ integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.0"
+ debug "^4.1.1"
+ minimatch "^3.0.4"
+
+"@humanwhocodes/object-schema@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
+ integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
+
"@jimp/bmp@^0.16.1":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.16.1.tgz#6e2da655b2ba22e721df0795423f34e92ef13768"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
"@nodelib/fs.walk@^1.2.3":
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz#94c23db18ee4653e129abd26fb06f870ac9e1ee2"
- integrity sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
dependencies:
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
node-fetch "^2.6.1"
"@openapitools/openapi-generator-cli@^2.1.4":
- version "2.3.5"
- resolved "https://registry.yarnpkg.com/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.3.5.tgz#20f3974879ae22beb18a0f5a3685cabacf380cef"
- integrity sha512-b9dX47j3+g08qM/EMg/Ftw2qBOpfhKB31xyPJ7+kBvGvcoNoMed3aPyojv1iWNfU1KlJvp6k9zJvViOND0ckGg==
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.3.7.tgz#5aaf9d178545874828db7c7c84a6f9a5b8ea00a4"
+ integrity sha512-4B93yPXop44fhAw6CT0eciaA0dRbPw5W7p2ZZ+HZ1uk4UD50zgaTAa9pnrsnCDnNtw2cvbZM0uCOf8xQyUy8Vg==
dependencies:
"@nestjs/common" "7.6.18"
"@nestjs/core" "7.6.18"
console.table "0.10.0"
fs-extra "10.0.0"
glob "7.1.6"
- inquirer "8.1.1"
+ inquirer "8.1.2"
lodash "4.17.21"
reflect-metadata "0.1.13"
- rxjs "7.1.0"
+ rxjs "7.2.0"
tslib "1.13.0"
"@sindresorhus/is@^0.14.0":
defer-to-connect "^1.0.1"
"@szmarczak/http-timer@^4.0.5":
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152"
- integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
+ integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
dependencies:
defer-to-connect "^2.0.0"
integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
"@tsconfig/node16@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1"
- integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==
-
-"@types/apicache@^1.2.0":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@types/apicache/-/apicache-1.2.2.tgz#b820659b1d95e66ec0e71dcd0317e9d30f0c154b"
- integrity sha512-+rjhMdbx7m7pKnNiQCSiKE21mGmMzsfCU871h5BCj4guhAj423j61Dq0Yrr9CnLiDwUhSKtkXWudr9SQE0/IoA==
- dependencies:
- "@types/redis" "*"
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
+ integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
"@types/async-lock@^1.1.0":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@types/async-lock/-/async-lock-1.1.2.tgz#cbc26a34b11b83b28f7783a843c393b443ef8bef"
- integrity sha512-j9n4bb6RhgFIydBe0+kpjnBPYumDaDyU8zvbWykyVMkku+c2CSu31MZkLeaBfqIwU+XCxlDpYDfyMQRkM0AkeQ==
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@types/async-lock/-/async-lock-1.1.3.tgz#0d86017cf87abbcb941c55360e533d37a3f23b3d"
+ integrity sha512-UpeDcjGKsYEQMeqEbfESm8OWJI305I7b9KE4ji3aBjoKWyN5CTdn8izcA1FM1DVDne30R5fNEnIy89vZw5LXJQ==
"@types/async@^3.0.0":
- version "3.2.6"
- resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.6.tgz#1d49339846c6aa0b0a8a08303c21176f1b64dc4f"
- integrity sha512-ZkrXnZLC1mc4b9QLKaSrsxV4oxTRs10OI2kgSApT8G0v1jrmqppSHUVQ15kLorzsFBTjvf7OKF4kAibuuNQ+xA==
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.7.tgz#f784478440d313941e7b12c2e4db53b0ed55637b"
+ integrity sha512-a+MBBfOTs3ShFMlbH9qsRVFkjIUunEtxrBT0gxRx1cntjKRg2WApuGmNYzHkwKaIhMi3SMbKktaD/rLObQMwIw==
"@types/bcrypt@^5.0.0":
version "5.0.0"
"@types/node" "*"
"@types/bluebird@^3.5.33":
- version "3.5.35"
- resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.35.tgz#3964c48372bf62d60616d8673dd77a9719ebac9b"
- integrity sha512-2WeeXK7BuQo7yPI4WGOBum90SzF/f8rqlvpaXx4rjeTmNssGRDHWf7fgDUH90xMB3sUOu716fUK5d+OVx0+ncQ==
+ version "3.5.36"
+ resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652"
+ integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==
"@types/body-parser@*", "@types/body-parser@^1.16.3":
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
- integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
+ version "1.19.1"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c"
+ integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==
dependencies:
"@types/connect" "*"
"@types/node" "*"
"@types/bull@^3.15.0":
- version "3.15.1"
- resolved "https://registry.yarnpkg.com/@types/bull/-/bull-3.15.1.tgz#3c3fd665b43ef383ca95a91b8d1448461fae0898"
- integrity sha512-thZyjxikoyuDa/ptZEqtTEPUjwlDenkpPigpIyad1X5UMp7U0fXTLiDHJjZ/5yXmVPuWx0cXFXj3drmva/UJRA==
+ version "3.15.2"
+ resolved "https://registry.yarnpkg.com/@types/bull/-/bull-3.15.2.tgz#b824b0b4fc8d1d9294a20973f6ceedcba1a7f3e8"
+ integrity sha512-uMQ7u/4GxY2bSTMd4P2yLkyqu3GoKbwTCDkMHJJ2g9OkiMq0Vxw+C7lF4w+oNkwZzZ2k4Kw76Ncxjd6GMnc+CA==
dependencies:
"@types/ioredis" "*"
"@types/bytes@^3.0.0":
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.1.0.tgz#835a3e4aea3b4d7604aca216a78de372bff3ecc3"
- integrity sha512-5YG1AiIC8HPPXRvYAIa7ehK3YMAwd0DWiPCtpuL9sgKceWLyWsVtLRA+lT4NkoanDNF9slwQ66lPizWDpgRlWA==
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.1.1.tgz#67a876422e660dc4c10a27f3e5bcfbd5455f01d0"
+ integrity sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==
"@types/cacheable-request@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976"
- integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9"
+ integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==
dependencies:
"@types/http-cache-semantics" "*"
"@types/keyv" "*"
"@types/chai" "*"
"@types/chai@*", "@types/chai@^4.0.4":
- version "4.2.19"
- resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.19.tgz#80f286b515897413c7a35bdda069cc80f2344233"
- integrity sha512-jRJgpRBuY+7izT7/WNXP/LsMO9YonsstuL+xuvycDyESpoDoIAsMd7suwpB4h9oEWB+ZlPTqJJ8EHomzNhwTPQ==
+ version "4.2.21"
+ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.21.tgz#9f35a5643129df132cf3b5c1ec64046ea1af0650"
+ integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg==
"@types/component-emitter@^1.2.10":
version "1.2.10"
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==
-"@types/config@^0.0.38":
- version "0.0.38"
- resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.38.tgz#ca30679b21b5b297299467e3a3f1c8e2e64b9170"
- integrity sha512-z2WizAfIFgSv8SQfQ8c0LlbDAcK47D/o93XW6bxZ9t3bs4fmmfAPjk1nhAIBTG84PBBCHfSPM+8g7vhLdbFokg==
+"@types/config@^0.0.39":
+ version "0.0.39"
+ resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.39.tgz#aad18ceb9439329adc3d4c6b91a908a72c715612"
+ integrity sha512-EBHj9lSIyw62vwqCwkeJXjiV6C2m2o+RJZlRWLkHduGYiNBoMXcY6AhSLqjQQ+uPdrPYrOMYvVa41zjo00LbFQ==
"@types/connect@*":
- version "3.4.34"
- resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901"
- integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==
+ version "3.4.35"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
+ integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
dependencies:
"@types/node" "*"
"@types/cookie@^0.4.0":
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108"
- integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
+ integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
"@types/cookiejar@*":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8"
integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==
-"@types/cors@^2.8.8":
- version "2.8.10"
- resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.10.tgz#61cc8469849e5bcdd0c7044122265c39cec10cf4"
- integrity sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==
+"@types/cors@^2.8.10":
+ version "2.8.12"
+ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
+ integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
"@types/express-rate-limit@^5.0.0":
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/@types/express-rate-limit/-/express-rate-limit-5.1.2.tgz#51f030ce722fe298269f85378b49a34837a1d2ca"
- integrity sha512-loN1dcr0WEKsbVtXNQKDef4Fmh25prfy+gESrwTDofIhAt17ngTxrsDiEZxLemmfHH279x206CdUB9XHXS9E6Q==
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz#79f2ca40d90455a5798da6f8e06d8a3d35f4a1d6"
+ integrity sha512-H+TYy3K53uPU2TqPGFYaiWc2xJV6+bIFkDd/Ma2/h67Pa6ARk9kWE0p/K9OH1Okm0et9Sfm66fmXoAxsH2PHXg==
dependencies:
"@types/express" "*"
"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18":
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz#a427278e106bca77b83ad85221eae709a3414d42"
- integrity sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==
+ version "4.17.24"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07"
+ integrity sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==
dependencies:
"@types/node" "*"
"@types/qs" "*"
"@types/range-parser" "*"
"@types/express@*":
- version "4.17.12"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.12.tgz#4bc1bf3cd0cfe6d3f6f2853648b40db7d54de350"
- integrity sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==
+ version "4.17.13"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
+ integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "^4.17.18"
"@types/serve-static" "*"
"@types/fluent-ffmpeg@^2.1.16":
- version "2.1.17"
- resolved "https://registry.yarnpkg.com/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.17.tgz#6958dda400fe1b33c21f3683db76905cb210d053"
- integrity sha512-/bdvjKw/mtBHlJ2370d04nt4CsWqU5MrwS/NtO96V01jxitJ4+iq8OFNcqc5CegeV3TQOK3uueK02kvRK+zjUg==
+ version "2.1.18"
+ resolved "https://registry.yarnpkg.com/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.18.tgz#72246c2f8c0f0a590aefc1cdbe13736c73f22a81"
+ integrity sha512-LTteOx3RUmnPlKkvhvW9aGOHdJYyEtIiRBVbYVO/zPU65ZYQelbPJ+zBBT+IXup7doMvxVstX7NMoUTWKZOhww==
dependencies:
"@types/node" "*"
"@types/fs-extra@^9.0.1":
- version "9.0.11"
- resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.11.tgz#8cc99e103499eab9f347dbc6ca4e99fb8d2c2b87"
- integrity sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==
+ version "9.0.12"
+ resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.12.tgz#9b8f27973df8a7a3920e8461517ebf8a7d4fdfaf"
+ integrity sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==
dependencies:
"@types/node" "*"
"@types/http-cache-semantics@*":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a"
- integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
+ integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
"@types/ioredis@*":
- version "4.26.4"
- resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.26.4.tgz#a2b1ed51ddd2c707d7eaac5017cc34a0fe51558a"
- integrity sha512-QFbjNq7EnOGw6d1gZZt2h26OFXjx7z+eqEnbCHSrDI1OOLEgOHMKdtIajJbuCr9uO+X9kQQRe7Lz6uxqxl5XKg==
+ version "4.26.6"
+ resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.26.6.tgz#7e332d6d24f12d79a1099834ccfa0c169ef667ed"
+ integrity sha512-Q9ydXL/5Mot751i7WLCm9OGTj5jlW3XBdkdEW21SkXZ8Y03srbkluFGbM3q8c+vzPW30JOLJ+NsZWHoly0+13A==
dependencies:
"@types/node" "*"
"@types/json-schema@^7.0.6", "@types/json-schema@^7.0.7":
- version "7.0.7"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
- integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
-
-"@types/json5@^0.0.29":
- version "0.0.29"
- resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
- integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
+ version "7.0.8"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
+ integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==
"@types/keyv@*":
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7"
- integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.2.tgz#5d97bb65526c20b6e0845f6b0d2ade4f28604ee5"
+ integrity sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==
dependencies:
"@types/node" "*"
"@types/lodash@^4.14.64":
- version "4.14.170"
- resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
- integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==
+ version "4.14.171"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.171.tgz#f01b3a5fe3499e34b622c362a46a609fdb23573b"
+ integrity sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg==
"@types/lru-cache@^5.1.0":
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03"
- integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef"
+ integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==
"@types/magnet-uri@*", "@types/magnet-uri@^5.1.1":
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.2.tgz#7860417399d52ddc0be1021d570b4ac93ffc133e"
- integrity sha512-bXFPXskwHoEYP6t8rq4nWchOlbUzXkyhnfCVZmq+zb25R5pWkasw7BmTIqDKQ6RAQmq89jll1v23yLa/SvPfAw==
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.3.tgz#cdf974721012bd758c0f559cabcad7bab87f9008"
+ integrity sha512-FvJN1yYdLhvU6zWJ2YnWQ2GnpFLsA8bt+85WY0tLh6ehzGNrvBorjlcc53/zY43r/IKn+ctFs1nt7andwGnQCQ==
dependencies:
"@types/node" "*"
-"@types/maildev@^0.0.2":
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/@types/maildev/-/maildev-0.0.2.tgz#936f21d66d2c38fafdd653d5bee8b642eb1dab89"
- integrity sha512-ITMKrdajIgqe5lz0BrU2xFB3yN4gX/+a2vemuPfgURlcxLn7V5i9AuzGQl2wiH2cg7zcZBqh8EHX+z3ufF7AUA==
+"@types/maildev@^0.0.3":
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/@types/maildev/-/maildev-0.0.3.tgz#8a7e3cc640d5388d86bcd11f6c18e40926244b87"
+ integrity sha512-fY5WoW3zsW686UFKf5ISIWiolaYoo+kbFE/B1rOHNJ768gdyIgu3Wol02vwanq2gFQO420iTUDaZ7ZpQbjZ57Q==
dependencies:
"@types/node" "*"
"@types/memoizee@^0.4.2":
- version "0.4.5"
- resolved "https://registry.yarnpkg.com/@types/memoizee/-/memoizee-0.4.5.tgz#cb4e7031decf698c52c4f57c348180b0385aa7da"
- integrity sha512-+ZzZZ3+0a7/ajBPeAAD4+LxrBsCat0EFZQtO3o0rwpIeLmDmSaM8KF/oYPuFxeUFAMiHIHFcGucFnY/8S4Hszg==
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/@types/memoizee/-/memoizee-0.4.6.tgz#a4ba7a3ea61fa45be916f148763bec2ca38c34cf"
+ integrity sha512-qJezGqoi3pW9Pset2w1Gfv8jATvmHHHnpO9Dq8x8pJGyYIpiUZJqRU0NM7xenmN0AcXEe7vqshI8H98KeFLYcg==
"@types/mime@^1":
version "1.3.2"
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
"@types/minimatch@^3.0.3":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
- integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
+ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
"@types/mkdirp@^1.0.0":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.1.tgz#0930b948914a78587de35458b86c907b6e98bbf6"
- integrity sha512-HkGSK7CGAXncr8Qn/0VqNtExEE+PHMWb+qlR1faHMao7ng6P3tAaoWWBMdva0gL5h4zprjIO89GJOLXsMcDm1Q==
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.2.tgz#8d0bad7aa793abe551860be1f7ae7f3198c16666"
+ integrity sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==
dependencies:
"@types/node" "*"
"@types/mocha@^8.0.3":
- version "8.2.2"
- resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0"
- integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==
+ version "8.2.3"
+ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323"
+ integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==
"@types/morgan@^1.7.32":
- version "1.9.2"
- resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.2.tgz#450f958a4d3fb0694a3ba012b09c8106f9a2885e"
- integrity sha512-edtGMEdit146JwwIeyQeHHg9yID4WSolQPxpEorHmN3KuytuCHyn2ELNr5Uxy8SerniFbbkmgKMrGM933am5BQ==
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.3.tgz#ae04180dff02c437312bc0cfb1e2960086b2f540"
+ integrity sha512-BiLcfVqGBZCyNCnCH3F4o2GmDLrpy0HeBVnNlyZG4fo88ZiE9SoiBe3C+2ezuwbjlEyT+PDZ17//TAlRxAn75Q==
dependencies:
"@types/node" "*"
"@types/multer@^1.3.3":
- version "1.4.6"
- resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.6.tgz#411950b7a99ba0de6ee8f6e3713f4628980cdc73"
- integrity sha512-F4EZ+KRrzdiSm3jSFj1GVUlw3zWXus5nXYBbrQW/0MGIUv9YHw1dM0cJOxq++v2+Gl4IBdSDvQ3YCORLdyCU+Q==
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e"
+ integrity sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==
dependencies:
"@types/express" "*"
-"@types/node@*", "@types/node@>=10.0.0", "@types/node@^15.0.1":
- version "15.12.4"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26"
- integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==
+"@types/node@*", "@types/node@>=10.0.0":
+ version "16.4.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.0.tgz#2c219eaa3b8d1e4d04f4dd6e40bc68c7467d5272"
+ integrity sha512-HrJuE7Mlqcjj+00JqMWpZ3tY8w7EUd+S0U3L1+PQSWiXZbOgyQDvi+ogoUxaHApPJq5diKxYBQwA3iIlNcPqOg==
"@types/node@^14.14.31":
- version "14.17.4"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.4.tgz#218712242446fc868d0e007af29a4408c7765bc0"
- integrity sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==
+ version "14.17.5"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.5.tgz#b59daf6a7ffa461b5648456ca59050ba8e40ed54"
+ integrity sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==
+
+"@types/node@^15.0.1":
+ version "15.14.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.2.tgz#7af8ab20156586f076f4760bc1b3c5ddfffd1ff2"
+ integrity sha512-dvMUE/m2LbXPwlvVuzCyslTEtQ2ZwuuFClDrOQ6mp2CenCg971719PTILZ4I6bTP27xfFFc+o7x2TkLuun/MPw==
"@types/nodemailer@^6.2.0":
- version "6.4.2"
- resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.2.tgz#d8ee254c969e6ad83fb9a0a0df3a817406a3fa3b"
- integrity sha512-yhsqg5Xbr8aWdwjFS3QjkniW5/tLpWXtOYQcJdo9qE3DolBxsKzgRCQrteaMY0hos8MklJNSEsMqDpZynGzMNg==
+ version "6.4.4"
+ resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b"
+ integrity sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==
dependencies:
"@types/node" "*"
"@types/normalize-package-data@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
- integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
+ integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
"@types/oauth2-server@^3.0.8":
- version "3.0.12"
- resolved "https://registry.yarnpkg.com/@types/oauth2-server/-/oauth2-server-3.0.12.tgz#3c404055c2c88068a3ee8f5e5a0c5a12bca8c365"
- integrity sha512-biRndg8t05UxbW1Aqe9kqDbzoi3wSgKITQxtLKR2eK0SwWTgF6AS32IyriFX6qf8KZWhruViVat7MuFfuAUrZQ==
+ version "3.0.13"
+ resolved "https://registry.yarnpkg.com/@types/oauth2-server/-/oauth2-server-3.0.13.tgz#e93baf99a923ffbb9ef09dea9978ee63d706b96c"
+ integrity sha512-thC6D0vgqUh2LFeOV7AzuWaAjZfciFmnh2tM10Nw4ZllMnTP7jw8PYMY6ti7PHAkwp4Cz9YFZs2LFwlXlA87Bw==
dependencies:
"@types/express" "*"
"@types/parse-torrent-file@*":
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/@types/parse-torrent-file/-/parse-torrent-file-4.0.2.tgz#40c96fc075aec256514807c6c381d11d9035bd9e"
- integrity sha512-EzdzpcN0sStQ35sUV2SChTJErLsbotsxZ/RYeR9gf3zXKlPLKaA7aIAoS/nuLRvfxH8mbrWQmXSw76alKecSdg==
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/@types/parse-torrent-file/-/parse-torrent-file-4.0.3.tgz#045b023426d168e0253c932cb782b231b1ee2d62"
+ integrity sha512-dFkPnJPKiFWiGX+HXmyTVt2js3k0d9dThmUxX8nfGC22hbyZ5BTmetsEl45sQhHLcFo43njVrIKMXM3F1ahXRw==
dependencies:
"@types/node" "*"
"@types/parse-torrent@*":
- version "5.8.3"
- resolved "https://registry.yarnpkg.com/@types/parse-torrent/-/parse-torrent-5.8.3.tgz#ff4e987d09ad27ccc1c8893b3a2c6a31a3bc4042"
- integrity sha512-c0xAjnpov+Xk/2HTtpaBm0tukNIAoZoxrqgTDwSaIu6IVCynY+2YD9zcQNk2P6H4atcXzD78/LI2CQzLlMmAJg==
+ version "5.8.4"
+ resolved "https://registry.yarnpkg.com/@types/parse-torrent/-/parse-torrent-5.8.4.tgz#c095834a9a815507c59014a79517ad403e4329d0"
+ integrity sha512-FdKs5yN5iYO5Cu9gVz1Zl30CbZe6HTsqloWmCf+LfbImgSzlsUkov2+npQWCQSQ3zi/a2G5C824K0UpZ2sRufA==
dependencies:
"@types/magnet-uri" "*"
"@types/node" "*"
"@types/parse-torrent-file" "*"
"@types/pem@^1.9.3":
- version "1.9.5"
- resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.9.5.tgz#cd5548b5e0acb4b41a9e21067e9fcd8c57089c99"
- integrity sha512-C0txxEw8B7DCoD85Ko7SEvzUogNd5VDJ5/YBG8XUcacsOGqxr5Oo4g3OUAfdEDUbhXanwUoVh/ZkMFw77FGPQQ==
+ version "1.9.6"
+ resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.9.6.tgz#c3686832e935947fdd9d848dec3b8fe830068de7"
+ integrity sha512-IC67SxacM9fxEi/w7hf98dTun83OwUMeLMo1NS2gE0wdM9MHeg73iH/Pp9nB02OUCQ7Zb2UuKE/IpFCmQw9jxw==
dependencies:
"@types/node" "*"
"@types/qs@*":
- version "6.9.6"
- resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1"
- integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==
+ version "6.9.7"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
+ integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
"@types/range-parser@*":
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
- integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
+ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
-"@types/redis@*", "@types/redis@^2.8.5":
- version "2.8.30"
- resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.30.tgz#2b63ce9ff93959355d8a1f6d7a45e483b5fe0299"
- integrity sha512-4D3XwfIc671FSNXNruE/wmf6jWL7QYtyAhiWXJDkY41F4atMnOol4584oP4WqnW3uHe8d+Jn+wDLuQaxbfMgXQ==
+"@types/redis@^2.8.5":
+ version "2.8.31"
+ resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.31.tgz#c11c1b269fec132ac2ec9eb891edf72fc549149e"
+ integrity sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==
dependencies:
"@types/node" "*"
"@types/request@^2.0.3":
- version "2.48.5"
- resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.5.tgz#019b8536b402069f6d11bee1b2c03e7f232937a0"
- integrity sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==
+ version "2.48.6"
+ resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.6.tgz#2300e7fc443108f79efa90e3bdf34c6d60fa89d8"
+ integrity sha512-vrZaV3Ij7j/l/3hz6OttZFtpRCu7zlq7XgkYHJP6FwVEAZkGQ095WqyJV08/GlW9eyXKVcp/xmtruHm8eHpw1g==
dependencies:
"@types/caseless" "*"
"@types/node" "*"
"@types/node" "*"
"@types/sax@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.1.tgz#e0248be936ece791a82db1a57f3fb5f7c87e8172"
- integrity sha512-dqYdvN7Sbw8QT/0Ci5rhjE4/iCMJEM0Y9rHpCu+gGXD9Lwbz28t6HI2yegsB6BoV1sShRMU6lAmAcgRjmFy7LA==
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.3.tgz#b630ac1403ebd7812e0bf9a10de9bf5077afb348"
+ integrity sha512-+QSw6Tqvs/KQpZX8DvIl3hZSjNFLW/OqE5nlyHXtTwODaJvioN2rOWpBNEWZp2HZUFhOh+VohmJku/WxEXU2XA==
dependencies:
"@types/node" "*"
"@types/serve-static@*":
- version "1.13.9"
- resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e"
- integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==
+ version "1.13.10"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
+ integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
dependencies:
"@types/mime" "^1"
"@types/node" "*"
"@types/simple-peer@*":
- version "9.11.0"
- resolved "https://registry.yarnpkg.com/@types/simple-peer/-/simple-peer-9.11.0.tgz#72f369cb2bebd0023b265aa726d352bf744f9f4b"
- integrity sha512-HjIGo3D5I2tdtl2FpngcDYHgqlDxZuZqmQn7f0TQrpYI4ZbuHbBg9THoiDjzKjCzZsHrG5Ag53m5O/cBYfjQWA==
+ version "9.11.1"
+ resolved "https://registry.yarnpkg.com/@types/simple-peer/-/simple-peer-9.11.1.tgz#bef6ff1e75178d83438e33aa6a4df2fd98fded1d"
+ integrity sha512-Pzqbau/WlivSXdRC0He2Wz/ANj2wbi4gzJrtysZz93jvOyI2jo/ibMjUe6AvPllFl/UO6QXT/A0Rcp44bDQB5A==
dependencies:
"@types/node" "*"
"@types/superagent@*":
- version "4.1.11"
- resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.11.tgz#4822bc64a82a0f579261a77097dbca276556c20e"
- integrity sha512-cZkWBXZI+jESnUTp8RDGBmk1Zn2MkScP4V5bjD7DyqB7L0WNWpblh4KX5K/6aTqxFZMhfo1bhi2cwoAEDVBBJw==
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.12.tgz#fad68c6712936892ad24cf94f2f7a07cc749fd0f"
+ integrity sha512-1GQvD6sySQPD6p9EopDFI3f5OogdICl1sU/2ij3Esobz/RtL9fWZZDPmsuv7eiy5ya+XNiPAxUcI3HIUTJa+3A==
dependencies:
"@types/cookiejar" "*"
"@types/node" "*"
"@types/superagent" "*"
"@types/tough-cookie@*":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d"
- integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40"
+ integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==
"@types/tv4@*":
- version "1.2.30"
- resolved "https://registry.yarnpkg.com/@types/tv4/-/tv4-1.2.30.tgz#3159a6fd5ac90c42d27aecfb20a6a150fb565668"
- integrity sha512-Uj68uOn6T94IQsEGxLRrFiAqYsP4AUaXiYWrm+DR9/PNtIxuXaq/oHwBbGVR0uXHox4UZMKxCuf+z5M40MpoBw==
+ version "1.2.31"
+ resolved "https://registry.yarnpkg.com/@types/tv4/-/tv4-1.2.31.tgz#b33f3e6f082782a90f1fc5f414ad8722db8c9baa"
+ integrity sha512-P97XU07fcpauSw3/fE2Q7eF6bHl4oHhwkikjnM7zlQLENrdC2rZuHSdNlMBhnW82NyBEsVJHII1Jk3d/MtQsQQ==
"@types/validator@^13.0.0":
- version "13.1.4"
- resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.1.4.tgz#d2e3c27523ce1b5d9dc13d16cbce65dc4db2adbe"
- integrity sha512-19C02B8mr53HufY7S+HO/EHBD7a/R22IwEwyqiHaR19iwL37dN3o0M8RianVInfSSqP7InVSg/o0mUATM4JWsQ==
+ version "13.6.3"
+ resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.6.3.tgz#31ca2e997bf13a0fffca30a25747d5b9f7dbb7de"
+ integrity sha512-fWG42pMJOL4jKsDDZZREnXLjc3UE0R8LOJfARWYg6U966rxDT7TYejYzLnUF5cvSObGg34nd0+H2wHHU5Omdfw==
"@types/webtorrent@^0.109.0":
- version "0.109.0"
- resolved "https://registry.yarnpkg.com/@types/webtorrent/-/webtorrent-0.109.0.tgz#dd377691caf360317738f67fa0c3bce48623df57"
- integrity sha512-c6EgbuFRZqhM4TMnloRuLAcR45j/Qn0kQ6CKWMppXXHfaQpspB1ZeeYx2Bpc22MAgCc3pjlAakTRS2h15stW2A==
+ version "0.109.1"
+ resolved "https://registry.yarnpkg.com/@types/webtorrent/-/webtorrent-0.109.1.tgz#6ca843c3a6d442459b558ec25ce290437f204900"
+ integrity sha512-yH0F7Ma9VI7Y1y02ZIOkDlS9WDoTFwesUGUFxjDEE6OFLlSqIKxgdHY72cigr7JHCwDm6uNQnCq+twz0SO6cTw==
dependencies:
"@types/bittorrent-protocol" "*"
"@types/node" "*"
"@types/simple-peer" "*"
"@types/ws@^7.2.1":
- version "7.4.5"
- resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.5.tgz#8ff0f7efcd8fea19f51f9dd66cb8b498d172a752"
- integrity sha512-8mbDgtc8xpxDDem5Gwj76stBDJX35KQ3YBoayxlqUQcL5BZUthiqP/VQ4PQnLHqM4PmlbyO74t98eJpURO+gPA==
+ version "7.4.7"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702"
+ integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^4.8.1":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz#1a66f03b264844387beb7dc85e1f1d403bd1803f"
- integrity sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.4.tgz#e73c8cabbf3f08dee0e1bda65ed4e622ae8f8921"
+ integrity sha512-s1oY4RmYDlWMlcV0kKPBaADn46JirZzvvH7c2CtAqxCY96S538JRBAzt83RrfkDheV/+G/vWNK0zek+8TB3Gmw==
dependencies:
- "@typescript-eslint/experimental-utils" "4.28.0"
- "@typescript-eslint/scope-manager" "4.28.0"
+ "@typescript-eslint/experimental-utils" "4.28.4"
+ "@typescript-eslint/scope-manager" "4.28.4"
debug "^4.3.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.1.0"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/experimental-utils@4.28.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz#13167ed991320684bdc23588135ae62115b30ee0"
- integrity sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==
+"@typescript-eslint/experimental-utils@4.28.4":
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.4.tgz#9c70c35ebed087a5c70fb0ecd90979547b7fec96"
+ integrity sha512-OglKWOQRWTCoqMSy6pm/kpinEIgdcXYceIcH3EKWUl4S8xhFtN34GQRaAvTIZB9DD94rW7d/U7tUg3SYeDFNHA==
dependencies:
"@types/json-schema" "^7.0.7"
- "@typescript-eslint/scope-manager" "4.28.0"
- "@typescript-eslint/types" "4.28.0"
- "@typescript-eslint/typescript-estree" "4.28.0"
+ "@typescript-eslint/scope-manager" "4.28.4"
+ "@typescript-eslint/types" "4.28.4"
+ "@typescript-eslint/typescript-estree" "4.28.4"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/parser@^4.0.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.0.tgz#2404c16751a28616ef3abab77c8e51d680a12caa"
- integrity sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.4.tgz#bc462dc2779afeefdcf49082516afdc3e7b96fab"
+ integrity sha512-4i0jq3C6n+og7/uCHiE6q5ssw87zVdpUj1k6VlVYMonE3ILdFApEzTWgppSRG4kVNB/5jxnH+gTeKLMNfUelQA==
dependencies:
- "@typescript-eslint/scope-manager" "4.28.0"
- "@typescript-eslint/types" "4.28.0"
- "@typescript-eslint/typescript-estree" "4.28.0"
+ "@typescript-eslint/scope-manager" "4.28.4"
+ "@typescript-eslint/types" "4.28.4"
+ "@typescript-eslint/typescript-estree" "4.28.4"
debug "^4.3.1"
-"@typescript-eslint/scope-manager@4.28.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz#6a3009d2ab64a30fc8a1e257a1a320067f36a0ce"
- integrity sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==
+"@typescript-eslint/scope-manager@4.28.4":
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.4.tgz#bdbce9b6a644e34f767bd68bc17bb14353b9fe7f"
+ integrity sha512-ZJBNs4usViOmlyFMt9X9l+X0WAFcDH7EdSArGqpldXu7aeZxDAuAzHiMAeI+JpSefY2INHrXeqnha39FVqXb8w==
dependencies:
- "@typescript-eslint/types" "4.28.0"
- "@typescript-eslint/visitor-keys" "4.28.0"
+ "@typescript-eslint/types" "4.28.4"
+ "@typescript-eslint/visitor-keys" "4.28.4"
-"@typescript-eslint/types@4.28.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.0.tgz#a33504e1ce7ac51fc39035f5fe6f15079d4dafb0"
- integrity sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==
+"@typescript-eslint/types@4.28.4":
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.4.tgz#41acbd79b5816b7c0dd7530a43d97d020d3aeb42"
+ integrity sha512-3eap4QWxGqkYuEmVebUGULMskR6Cuoc/Wii0oSOddleP4EGx1tjLnZQ0ZP33YRoMDCs5O3j56RBV4g14T4jvww==
-"@typescript-eslint/typescript-estree@4.28.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz#e66d4e5aa2ede66fec8af434898fe61af10c71cf"
- integrity sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==
+"@typescript-eslint/typescript-estree@4.28.4":
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.4.tgz#252e6863278dc0727244be9e371eb35241c46d00"
+ integrity sha512-z7d8HK8XvCRyN2SNp+OXC2iZaF+O2BTquGhEYLKLx5k6p0r05ureUtgEfo5f6anLkhCxdHtCf6rPM1p4efHYDQ==
dependencies:
- "@typescript-eslint/types" "4.28.0"
- "@typescript-eslint/visitor-keys" "4.28.0"
+ "@typescript-eslint/types" "4.28.4"
+ "@typescript-eslint/visitor-keys" "4.28.4"
debug "^4.3.1"
globby "^11.0.3"
is-glob "^4.0.1"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/visitor-keys@4.28.0":
- version "4.28.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz#255c67c966ec294104169a6939d96f91c8a89434"
- integrity sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==
+"@typescript-eslint/visitor-keys@4.28.4":
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.4.tgz#92dacfefccd6751cbb0a964f06683bfd72d0c4d3"
+ integrity sha512-NIAXAdbz1XdOuzqkJHjNKXKj8QQ4cv5cxR/g0uQhCYf/6//XrmfpaYsM7PnBcNbfvTDLUkqQ5TPNm1sozDdTWg==
dependencies:
- "@typescript-eslint/types" "4.28.0"
+ "@typescript-eslint/types" "4.28.4"
eslint-visitor-keys "^2.0.0"
"@ungap/promise-all-settled@1.1.2":
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@uploadx/core@^4.4.0":
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/@uploadx/core/-/core-4.4.0.tgz#27ea2b0d28125e81a6bdd65637dc5c7829306cc7"
- integrity sha512-dU0oDURYR5RvuAzf63EL9e/fCY4OOQKOs237UTbZDulbRbiyxwEZR+IpRYYr3hKRjjij03EF/Y5j54VGkebAKg==
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/@uploadx/core/-/core-4.4.2.tgz#13220a449e3ab23ed324e4beaea04dd56e538b10"
+ integrity sha512-wI9iWjuT+FDV/IjTj55xPs30MwiIMg4buoZlBnTiPAkgyxpwXi9F+6Zchjy2oE5Lfd/9enp0sQz/0RMfqVimAg==
dependencies:
bytes "^3.1.0"
debug "^4.3.1"
negotiator "0.6.2"
acorn-jsx@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
- integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^7.1.1, acorn@^7.4.0:
version "7.4.1"
uri-js "^4.2.2"
ajv@^8.0.1:
- version "8.6.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.0.tgz#60cc45d9c46a477d80d92c48076d972c342e5720"
- integrity sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==
+ version "8.6.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571"
+ integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
-anymatch@~3.1.1, anymatch@~3.1.2:
+anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
normalize-path "^3.0.0"
picomatch "^2.0.4"
-apicache@1.6.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/apicache/-/apicache-1.6.2.tgz#a0a3d51024fa2814c4ace7e9e7053ebcb0920ee6"
- integrity sha512-3z5e+1E2qwZoqzFVgdx5l9nGhSG0kHv3v2G170vnJSz5uj4mCLVZfRw0o37aWwV8pTPXSkB8OBZz3TIur4H26g==
-
append-field@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
autocannon@^7.0.4:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/autocannon/-/autocannon-7.3.0.tgz#8e52bb3f07926b573dcf401d3fe365393fbab808"
- integrity sha512-RuyTU8fQE1FC6BDgslofLCeI4y9y9RRnnZtvoQ+onwQl+B2rsiGpcCi84/Si0rq3VRkkMFnmPulY3z59zYhX9g==
+ version "7.4.0"
+ resolved "https://registry.yarnpkg.com/autocannon/-/autocannon-7.4.0.tgz#7e3ea188501d60162b7a0167c1d9bf90db870c2e"
+ integrity sha512-X0g/nkJ7oHkfn/B+LUzz9jPjG4nD48tPnu2E24m7LA7p8+Mvd/Clrb+FnHmPgI7pszXPRtzUYWz6QrSyMiEY6w==
dependencies:
chalk "^4.1.0"
char-spinner "^1.0.1"
resolved "https://registry.yarnpkg.com/bitfield/-/bitfield-4.0.0.tgz#3094123c870030dc6198a283d779639bd2a8e256"
integrity sha512-jtuSG9CQr5yoHFuvhgf50+DH8Aezl3C/mMSfqdG4DqP7Kqe34uBUtCEHPN9oWaldTm96/i7y5e778SnM5ES4rw==
-bittorrent-dht@^10.0.0:
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/bittorrent-dht/-/bittorrent-dht-10.0.0.tgz#01de59bb03ed86a8847cb533134925d236d7f565"
- integrity sha512-mrM18HMabvd3n/hQa4PYe942nWvBsJCBQb5PfT9kUJLlspNPGiulZYSCgWs7+XarS7nufYrGEp07f9eKTKIrgw==
+bittorrent-dht@^10.0.0, bittorrent-dht@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/bittorrent-dht/-/bittorrent-dht-10.0.1.tgz#ff2efe77cdb4d72c819f46b42a162f42ca233793"
+ integrity sha512-aR0vAgm+SgLiwTCEtNgeuqtT2deg+E/xHCTb7iryikvLbqbR58oFHbNYX4CM6EzyNGSKfcdBKp1gWI5Gcn2Aaw==
dependencies:
bencode "^2.0.0"
debug "^4.1.1"
resolved "https://registry.yarnpkg.com/bittorrent-peerid/-/bittorrent-peerid-1.3.3.tgz#b8dc79e421f8136d2ffd0b163a18e9d70da09949"
integrity sha512-tSh9HdQgwyEAfo1jzoGEis6o/zs4CcdRTchG93XVl5jct+DCAN90M5MVUV76k2vJ9Xg3GAzLB5NLsY/vnVTh6w==
-bittorrent-protocol@^3.3.1:
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/bittorrent-protocol/-/bittorrent-protocol-3.4.1.tgz#b481d09dbf910fa7fcca5f06a7c1c4246151d4d1"
- integrity sha512-3qBW4ZZrUZKN7HzHbX4+kbiphrTNeraMp3i9n3wobicysjibAV8SBDY+sGiBN4SgXV6WvEW4kyRPIjoSqW+khw==
+bittorrent-protocol@^3.4.2:
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/bittorrent-protocol/-/bittorrent-protocol-3.4.2.tgz#e5194d1acd30273ac02bb272c208977716d0394b"
+ integrity sha512-a7ueJzmCImWIXfKrJ+dT6mgqi5+LFByAXoMXhV/cYt/y8kplaC8N9ZWfpiTidJY4H2o1GTsyMy73o62a/rZ0Ow==
dependencies:
bencode "^2.0.1"
bitfield "^4.0.0"
- buffer-xor "^2.0.2"
debug "^4.3.1"
randombytes "^2.1.0"
rc4 "^0.1.5"
unordered-array-remove "^1.0.2"
bittorrent-tracker@^9.0.0:
- version "9.17.2"
- resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-9.17.2.tgz#1afb02d3d2fb474c13389c45e8a2b6919bff40bd"
- integrity sha512-hXjed0OnB16da+ScJUZnrAZbf9gMgSLKqh5rJebtYnTRgN4o1mX0DOPH3Nf5RFCs935ibhSmZN5nwbkh+3MdEA==
+ version "9.17.4"
+ resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-9.17.4.tgz#663f51064a924e945cb6ca19a0c293aca258128b"
+ integrity sha512-ykhdVQHtLfn4DYSJUQD/zFAbP8YwnF6nGlj2SBnCY4xkW5bhwXPeFZUhryAtdITl0qNL/FpmFOamBZfxIwkbxg==
dependencies:
bencode "^2.0.1"
bittorrent-peerid "^1.3.3"
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
-buffer-xor@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289"
- integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==
- dependencies:
- safe-buffer "^5.1.1"
-
buffer@^5.2.0, buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
node-gyp-build "^4.2.0"
bull@^3.4.2:
- version "3.22.9"
- resolved "https://registry.yarnpkg.com/bull/-/bull-3.22.9.tgz#9d86493e1bb4afeb7e6e259c45141185bd78111d"
- integrity sha512-waVaXkjS1+aPxZpmqcKKQX1KeWx7uZXcg9bhe+y5xx/3k8Xu0vqUL1FxMUfp0f3O4KSAHk1EDlD5DGXxBlFDFQ==
+ version "3.26.0"
+ resolved "https://registry.yarnpkg.com/bull/-/bull-3.26.0.tgz#c6198cf4f3a2fa5f3044cbe462b452c77a3df94f"
+ integrity sha512-W1ohwMBApLW9dhKHEwgzr8YnpScTOGC9KtKP2DrvjnWTQFWbaEnKlrDHKp3SJwvAB0C3jDsO579O/Hys/UmAiQ==
dependencies:
cron-parser "^2.13.0"
debuglog "^1.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
+cache-chunk-store@^3.2.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/cache-chunk-store/-/cache-chunk-store-3.2.2.tgz#19bb55d61252cd2174da4686548d52bc2dd44120"
+ integrity sha512-2lJdWbgHFFxcSth9s2wpId3CR3v1YC63KjP4T9WhpW7LWlY7Hiiei3QwwqzkWqlJTfR8lSy9F5kRQECeyj+yQA==
+ dependencies:
+ lru "^3.1.0"
+ queue-microtask "^1.2.3"
+
cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
parse5-htmlparser2-tree-adapter "^6.0.1"
tslib "^2.2.0"
-chokidar@3.5.1:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
- integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
- dependencies:
- anymatch "~3.1.1"
- braces "~3.0.2"
- glob-parent "~5.1.0"
- is-binary-path "~2.1.0"
- is-glob "~4.0.1"
- normalize-path "~3.0.0"
- readdirp "~3.5.0"
- optionalDependencies:
- fsevents "~2.3.1"
-
-chokidar@^3.2.2, chokidar@^3.4.2:
+chokidar@3.5.2, chokidar@^3.2.2, chokidar@^3.4.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.5.2:
- version "1.5.5"
- resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014"
- integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
+ integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
dayjs@^1.10.4:
- version "1.10.5"
- resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
- integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==
+ version "1.10.6"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63"
+ integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==
debug@2.6.9, debug@^2.2.0, debug@^2.6.9:
version "2.6.9"
dependencies:
ms "2.0.0"
-debug@4, debug@4.3.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@~4.3.1:
+debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@~4.3.1:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
+ integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
+ dependencies:
+ ms "2.1.2"
+
+debug@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
xmlhttprequest-ssl "~1.5.4"
yeast "0.1.2"
-engine.io-client@~5.1.1:
+engine.io-client@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-5.1.2.tgz#27108da9b39ae03262443d945caf2caa3655c4cb"
integrity sha512-blRrgXIE0A/eurWXRzvfCLG7uUFJqfTGFsyJzXSK71srMMGJ2VraBLg8Mdw28uUxSpVicepBN9X7asqpD1mZcQ==
engine.io-parser "~2.1.0"
ws "~6.1.0"
-engine.io@~5.1.0:
+engine.io@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-5.1.1.tgz#a1f97e51ddf10cbd4db8b5ff4b165aad3760cdd3"
integrity sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
eslint@^7.2.0:
- version "7.29.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.29.0.tgz#ee2a7648f2e729485e4d0bd6383ec1deabc8b3c0"
- integrity sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==
+ version "7.31.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca"
+ integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==
dependencies:
"@babel/code-frame" "7.12.11"
- "@eslint/eslintrc" "^0.4.2"
+ "@eslint/eslintrc" "^0.4.3"
+ "@humanwhocodes/config-array" "^0.5.0"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
integrity sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=
express-rate-limit@^5.0.0:
- version "5.2.6"
- resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.2.6.tgz#b454e1be8a252081bda58460e0a25bf43ee0f7b0"
- integrity sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA==
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.3.0.tgz#e7b9d3c2e09ece6e0406a869b2ce00d03fe48aea"
+ integrity sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==
express-validator@^6.4.0:
version "6.12.0"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-glob@^3.1.1:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
- integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
+ integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
- glob-parent "^5.1.0"
+ glob-parent "^5.1.2"
merge2 "^1.3.0"
- micromatch "^4.0.2"
- picomatch "^2.2.1"
+ micromatch "^4.0.4"
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
-fast-safe-stringify@2.0.7, fast-safe-stringify@^2.0.4, fast-safe-stringify@^2.0.7:
+fast-safe-stringify@2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
+fast-safe-stringify@^2.0.4, fast-safe-stringify@^2.0.7:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f"
+ integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==
+
fast-xml-parser@^3.19.0:
version "3.19.0"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz#cb637ec3f3999f51406dd8ff0e6fc4d83e520d01"
integrity sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==
fastq@^1.6.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858"
- integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807"
+ integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==
dependencies:
reusify "^1.0.4"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
- integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.1.tgz#bbef080d95fca6709362c73044a1634f7c6e7d05"
+ integrity sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==
fluent-ffmpeg@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@~2.3.1, fsevents@~2.3.2:
+fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
image-q "^1.1.1"
omggif "^1.0.10"
-glob-parent@^5.1.0, glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2:
+glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
process "^0.11.10"
globals@^13.6.0, globals@^13.9.0:
- version "13.9.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.9.0.tgz#4bf2bf635b334a173fb1daf7c5e6b218ecdc06cb"
- integrity sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==
+ version "13.10.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.10.0.tgz#60ba56c3ac2ca845cfbf4faeca727ad9dd204676"
+ integrity sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==
dependencies:
type-fest "^0.20.2"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
hyperid@^2.0.3:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/hyperid/-/hyperid-2.1.0.tgz#2f5ed7537e87e8fddd344710a610be501b3d2da6"
- integrity sha512-cSakhxbUsaIuqjfvvcUuvl/Fl342J65xgLLYrYxSSr9qmJ/EJK+S8crS6mIlQd/a7i+Pe4D0MgSrtZPLze+aCw==
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/hyperid/-/hyperid-2.3.1.tgz#70cc2c917b6367c9f7307718be243bc28b258353"
+ integrity sha512-mIbI7Ymn6MCdODaW1/6wdf5lvvXzmPsARN4zTLakMmcziBOuP4PxCBJvHF6kbAIHX6H4vAELx/pDmt0j6Th5RQ==
dependencies:
- uuid "^3.4.0"
+ uuid "^8.3.2"
uuid-parse "^1.1.0"
i18n-locales@^0.0.5:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-inquirer@8.1.1:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.1.tgz#7c53d94c6d03011c7bb2a947f0dca3b98246c26a"
- integrity sha512-hUDjc3vBkh/uk1gPfMAD/7Z188Q8cvTGl0nxwaCdwSbzFh6ZKkZh+s2ozVxbE5G9ZNRyeY0+lgbAIOUFsFf98w==
+inquirer@8.1.2:
+ version "8.1.2"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.2.tgz#65b204d2cd7fb63400edd925dfe428bafd422e3d"
+ integrity sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
mute-stream "0.0.8"
ora "^5.3.0"
run-async "^2.4.0"
- rxjs "^6.6.6"
+ rxjs "^7.2.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
cidr-regex "^3.1.1"
is-core-module@^2.2.0, is-core-module@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
- integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491"
+ integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==
dependencies:
has "^1.0.3"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
-json5@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
- integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
- dependencies:
- minimist "^1.2.0"
-
-json5@^2.1.1:
+json5@^2.1.1, json5@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
integrity sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==
markdown-it@^12.0.4:
- version "12.0.6"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.6.tgz#adcc8e5fe020af292ccbdf161fe84f1961516138"
- integrity sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==
+ version "12.1.0"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.1.0.tgz#7ad572caddd336bd27a68d20e86bac1fafe8fb20"
+ integrity sha512-7temG6IFOOxfU0SgzhqR+vr2diuMhyO5uUIEZ3C5NbXhqC9uFUHoU41USYuDFoZRsaY7BEIEei874Z20VMLF6A==
dependencies:
argparse "^2.0.1"
entities "~2.1.0"
integrity sha512-zxK5E4jbuARALc+fIUAanM2njVGnrd9YvKrqoDHUg2XwNLJijo39EzMIg59LecHBHsIHNtPqepqnJp4SmL/EVg==
marked@^2.0.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/marked/-/marked-2.1.2.tgz#59579e17b02443312caa1509994d5a0b18ae38e1"
- integrity sha512-ueJhIvklJJw04qxQbGIAu63EXwwOCYc7yKMBjgagTM4rjC5QtWyqSNgW7jCosV1/Km/1TUfs5qEpAqcGG0Mo5g==
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-2.1.3.tgz#bd017cef6431724fd4b27e0657f5ceb14bff3753"
+ integrity sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==
math-interval-parser@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-micromatch@^4.0.2:
+micromatch@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mocha@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.1.tgz#01e66b7af0012330c0a38c4b6eaa6d92b8a81bf9"
- integrity sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.2.tgz#e84849b61f406a680ced85af76425f6f3108d1a0"
+ integrity sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==
dependencies:
"@ungap/promise-all-settled" "1.1.2"
ansi-colors "4.1.1"
browser-stdout "1.3.1"
- chokidar "3.5.1"
+ chokidar "3.5.2"
debug "4.3.1"
diff "5.0.0"
escape-string-regexp "4.0.0"
minimatch "3.0.4"
ms "2.1.3"
nanoid "3.1.23"
- serialize-javascript "5.0.1"
+ serialize-javascript "6.0.0"
strip-json-comments "3.1.1"
supports-color "8.1.1"
which "2.0.2"
wide-align "1.1.3"
- workerpool "6.1.4"
+ workerpool "6.1.5"
yargs "16.2.0"
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==
node-media-server@^2.1.4:
- version "2.2.8"
- resolved "https://registry.yarnpkg.com/node-media-server/-/node-media-server-2.2.8.tgz#586569690733ff76309f8ff50cdf302f30207009"
- integrity sha512-sLusJjFVJ3mWeDMHnkyx1gitPjsMcWbhzlXT7wC8gRRjP0HKmY3d8wGLjl0s+JVPB6ruwSZw0mAwntOwrOCnRw==
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/node-media-server/-/node-media-server-2.3.8.tgz#05ad4d1ea9372d4dd5f7b72fb5f1c00da44ce78b"
+ integrity sha512-IWji6X4RQHoiAu0mTojtQ7dznrdsHRahXG51d8um0bjFKkmtJHN3W9oA2fVtFtDrAYMC5bG9GvGDO2qdZtgzww==
dependencies:
basic-auth-connect "^1.0.0"
chalk "^2.4.2"
dateformat "^3.0.3"
express "^4.16.4"
lodash ">=4.17.13"
+ minimist "^1.2.5"
mkdirp "1.0.3"
ws "^7.4.6"
integrity sha1-/r+sy0vSc2eEc6MJxstLSi88SOM=
nodemailer@^6.0.0, nodemailer@^6.5.0, nodemailer@^6.6.0:
- version "6.6.2"
- resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.2.tgz#e184c9ed5bee245a3e0bcabc7255866385757114"
- integrity sha512-YSzu7TLbI+bsjCis/TZlAXBoM4y93HhlIgo0P5oiA2ua9Z4k+E2Fod//ybIzdJxOlXGRcHIh/WaeCBehvxZb/Q==
+ version "6.6.3"
+ resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.3.tgz#31fb53dd4d8ae16fc088a65cb9ffa8d928a69b48"
+ integrity sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==
nodemon@^2.0.1:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32"
- integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==
+ version "2.0.12"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.12.tgz#5dae4e162b617b91f1873b3bfea215dd71e144d5"
+ integrity sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==
dependencies:
chokidar "^3.2.2"
debug "^3.2.6"
integrity sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ==
object-inspect@^1.10.3, object-inspect@^1.9.0:
- version "1.10.3"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
- integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
+ integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
postcss@^8.0.2:
- version "8.3.5"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
- integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
+ version "8.3.6"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea"
+ integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.23"
dependencies:
readable-stream "^1.1.13-1"
-readdirp@~3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
- integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
- dependencies:
- picomatch "^2.2.1"
-
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
resolve-alpn@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.1.2.tgz#30b60cfbb0c0b8dc897940fe13fe255afcdd4d28"
- integrity sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.0.tgz#058bb0888d1cd4d12474e9a4b6eb17bdd5addc44"
+ integrity sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68"
integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==
-rxjs@7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.1.0.tgz#94202d27b19305ef7b1a4f330277b2065df7039e"
- integrity sha512-gCFO5iHIbRPwznl6hAYuwNFld8W4S2shtSJIqG27ReWXo9IWrCyEICxUA+6vJHwSR/OakoenC4QsDxq50tzYmw==
+rxjs@7.2.0, rxjs@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.2.0.tgz#5cd12409639e9514a71c9f5f9192b2c4ae94de31"
+ integrity sha512-aX8w9OpKrQmiPKfT1bqETtUr9JygIz6GZ+gql8v7CijClsP0laoFUdKzxFAoWuRdSlOdU2+crss+cMf+cqMTnw==
dependencies:
tslib "~2.1.0"
-rxjs@^6.6.3, rxjs@^6.6.6:
+rxjs@^6.6.3:
version "6.6.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
validator "^10.11.0"
wkx "^0.5.0"
-serialize-javascript@5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
- integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==
+serialize-javascript@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
+ integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
dependencies:
randombytes "^2.1.0"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9"
integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==
-socket.io-adapter@~2.3.0:
+socket.io-adapter@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz#a442720cb09a4823cfb81287dda1f9b52d4ccdb2"
integrity sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==
to-array "0.1.4"
socket.io-client@^4.0.1:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.1.2.tgz#95ad7113318ea01fba0860237b96d71e1b1fd2eb"
- integrity sha512-RDpWJP4DQT1XeexmeDyDkm0vrFc0+bUsHDKiVGaNISJvJonhQQOMqV9Vwfg0ZpPJ27LCdan7iqTI92FRSOkFWQ==
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.1.3.tgz#236daa642a9f229932e00b7221e843bf74232a62"
+ integrity sha512-hISFn6PDpgDifVUiNklLHVPTMv1LAk8poHArfIUdXa+gKgbr0MZbAlquDFqCqsF30yBqa+jg42wgos2FK50BHA==
dependencies:
"@types/component-emitter" "^1.2.10"
backo2 "~1.0.2"
component-emitter "~1.3.0"
debug "~4.3.1"
- engine.io-client "~5.1.1"
+ engine.io-client "~5.1.2"
parseuri "0.0.6"
socket.io-parser "~4.0.4"
debug "~3.1.0"
isarray "2.0.1"
-socket.io-parser@~4.0.3, socket.io-parser@~4.0.4:
+socket.io-parser@~4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0"
integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==
socket.io-parser "~3.3.0"
socket.io@^4.0.1:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.1.2.tgz#f90f9002a8d550efe2aa1d320deebb9a45b83233"
- integrity sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.1.3.tgz#d114328ef27ab31b889611792959c3fa6d502500"
+ integrity sha512-tLkaY13RcO4nIRh1K2hT5iuotfTaIQw7cVIe0FUykN3SuQi0cm7ALxuyT5/CtDswOMWUzMGTibxYNx/gU7In+Q==
dependencies:
"@types/cookie" "^0.4.0"
- "@types/cors" "^2.8.8"
+ "@types/cors" "^2.8.10"
"@types/node" ">=10.0.0"
accepts "~1.3.4"
base64id "~2.0.0"
debug "~4.3.1"
- engine.io "~5.1.0"
- socket.io-adapter "~2.3.0"
- socket.io-parser "~4.0.3"
+ engine.io "~5.1.1"
+ socket.io-adapter "~2.3.1"
+ socket.io-parser "~4.0.4"
source-map-js@^0.6.2:
version "0.6.2"
semver "^7.3.2"
supertest@^6.0.1:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.1.3.tgz#3f49ea964514c206c334073e8dc4e70519c7403f"
- integrity sha512-v2NVRyP73XDewKb65adz+yug1XMtmvij63qIWHZzSX8tp6wiq6xBLUy4SUAd2NII6wIipOmHT/FD9eicpJwdgQ==
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.1.4.tgz#ea8953343e0ca316e80e975b39340934f754eb06"
+ integrity sha512-giC9Zm+Bf1CZP09ciPdUyl+XlMAu6rbch79KYiYKOGcbK2R1wH8h+APul1i/3wN6RF1XfWOIF+8X1ga+7SBrug==
dependencies:
methods "^1.1.2"
superagent "^6.1.0"
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
-ts-node@10.0.0:
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be"
- integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==
+ts-node@10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.1.0.tgz#e656d8ad3b61106938a867f69c39a8ba6efc966e"
+ integrity sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==
dependencies:
"@tsconfig/node10" "^1.0.7"
"@tsconfig/node12" "^1.0.7"
yn "3.1.1"
tsconfig-paths@^3.9.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
- integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7"
+ integrity sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==
dependencies:
- "@types/json5" "^0.0.29"
- json5 "^1.0.1"
+ json5 "^2.2.0"
minimist "^1.2.0"
strip-bom "^3.0.0"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^4.0.5:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.4.tgz#3f85b986945bcf31071decdd96cf8bfa65f9dcbc"
- integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==
+ version "4.3.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
+ integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6"
debug "^4.2.0"
simple-sha1 "^3.0.1"
-ut_pex@^3.0.0:
+ut_pex@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/ut_pex/-/ut_pex-3.0.1.tgz#fb8b6e066f8f6f6de3e6b3e28e7d18e697be5854"
integrity sha512-t1MHIDHSISgOJcmq8UM6Qv9/hRQYVaUvzqSNnXa5ATDbS9hXfhBpyBo2HcSyJtwPSHsmMtNui8G6yKirwJ8vow==
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-utp-native@^2.4.0:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/utp-native/-/utp-native-2.5.1.tgz#445a3fcf23db0a841a48c4e353f8900ea852b3e8"
- integrity sha512-wbrJwR8DZx8N9s1ffTcMuBK7tMBQ9tvKpIL+mWHrDvGUYfV7ivroEGFTXUr4meqy/PVbUdMfURSoBbwuGtt/YQ==
+utp-native@^2.5.3:
+ version "2.5.3"
+ resolved "https://registry.yarnpkg.com/utp-native/-/utp-native-2.5.3.tgz#7c04c2a8c2858716555a77d10adb9819e3119b25"
+ integrity sha512-sWTrWYXPhhWJh+cS2baPzhaZc89zwlWCfwSthUjGhLkZztyPhcQllo+XVVCbNGi7dhyRlxkWxN4NKU6FbA9Y8w==
dependencies:
napi-macros "^2.0.0"
node-gyp-build "^4.2.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
-uuid@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
- integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
xhr2 "^0.1.4"
webtorrent@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/webtorrent/-/webtorrent-1.0.2.tgz#acd0ae3bedcfa8cb732043489ff506d07d90140a"
- integrity sha512-uv9fq5md/98JyeDDyziy1H28Wc/idO80AKv+9pQ4XK0WNNjdE3FMtCKfrvU2VNS1PdAOrA6sFuUq2x0mV7k7WQ==
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/webtorrent/-/webtorrent-1.2.5.tgz#edea45c53b98787a472381ff91d41c9164b8ac51"
+ integrity sha512-EvtAQ3rK4c7Kf4ZGxYOGvi8Jih8qsZka1IgNB8T5Vxw5UzSNG1nxTVNNTXL0jFhQUMsyRwIOkTgd7ZkJY6bqsw==
dependencies:
addr-to-ip-port "^1.5.1"
bitfield "^4.0.0"
- bittorrent-dht "^10.0.0"
- bittorrent-protocol "^3.3.1"
+ bittorrent-dht "^10.0.1"
+ bittorrent-protocol "^3.4.2"
+ cache-chunk-store "^3.2.2"
chrome-net "^3.3.4"
chunk-store-stream "^4.3.0"
cpus "^1.0.3"
create-torrent "^4.7.0"
- debug "^4.3.1"
+ debug "^4.3.2"
end-of-stream "^1.4.4"
escape-html "^1.0.3"
fs-chunk-store "^2.0.3"
torrent-piece "^2.0.1"
unordered-array-remove "^1.0.2"
ut_metadata "^3.5.2"
- ut_pex "^3.0.0"
+ ut_pex "^3.0.1"
optionalDependencies:
- utp-native "^2.4.0"
+ utp-native "^2.5.3"
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
-workerpool@6.1.4:
- version "6.1.4"
- resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.4.tgz#6a972b6df82e38d50248ee2820aa98e2d0ad3090"
- integrity sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==
+workerpool@6.1.5:
+ version "6.1.5"
+ resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581"
+ integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==
wrap-ansi@^6.2.0:
version "6.2.0"
typedarray-to-buffer "^3.1.5"
ws@^7.0.0, ws@^7.4.2, ws@^7.4.5, ws@^7.4.6:
- version "7.5.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.0.tgz#0033bafea031fb9df041b2026fc72a571ca44691"
- integrity sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==
+ version "7.5.3"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
+ integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
ws@~6.1.0:
version "6.1.4"