diff --git a/client/angular.json b/client/angular.json index d929248d4..9b069422f 100644 --- a/client/angular.json +++ b/client/angular.json @@ -199,7 +199,11 @@ "is-plain-object", "parse-srcset", "deepmerge", - "core-js/features/reflect" + "core-js/features/reflect", + "@formatjs/intl-locale/polyfill", + "@formatjs/intl-locale/should-polyfill", + "@formatjs/intl-pluralrules/polyfill-force", + "@formatjs/intl-pluralrules/should-polyfill" ], "scripts": [], "vendorChunk": true, diff --git a/client/package.json b/client/package.json index 202a0f836..564e56ae7 100644 --- a/client/package.json +++ b/client/package.json @@ -47,6 +47,8 @@ "@angular/service-worker": "^16.0.2", "@babel/core": "^7.18.5", "@babel/preset-env": "^7.18.2", + "@formatjs/intl-locale": "^3.3.1", + "@formatjs/intl-pluralrules": "^5.2.2", "@ng-bootstrap/ng-bootstrap": "^14.0.1", "@ng-select/ng-select": "^10.0.3", "@ngx-loading-bar/core": "^6.0.0", diff --git a/client/src/app/+admin/config/edit-custom-config/edit-configuration.service.ts b/client/src/app/+admin/config/edit-custom-config/edit-configuration.service.ts index 628c2d102..42c0e6dc2 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-configuration.service.ts +++ b/client/src/app/+admin/config/edit-custom-config/edit-configuration.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core' import { FormGroup } from '@angular/forms' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' export type ResolutionOption = { id: string @@ -99,10 +99,7 @@ export class EditConfigurationService { return { value, atMost: noneOnAuto, // auto switches everything to a least estimation since ffmpeg will take as many threads as possible - unit: prepareIcu($localize`{value, plural, =1 {thread} other {threads}}`)( - { value }, - $localize`threads` - ) + unit: formatICU($localize`{value, plural, =1 {thread} other {threads}}`, { value }) } } } diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.ts b/client/src/app/+admin/follows/followers-list/followers-list.component.ts index cebb2e1a2..618892242 100644 --- a/client/src/app/+admin/follows/followers-list/followers-list.component.ts +++ b/client/src/app/+admin/follows/followers-list/followers-list.component.ts @@ -1,7 +1,7 @@ import { SortMeta } from 'primeng/api' import { Component, OnInit } from '@angular/core' import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' import { AdvancedInputFilter } from '@app/shared/shared-forms' import { InstanceFollowService } from '@app/shared/shared-instance' import { DropdownAction } from '@app/shared/shared-main' @@ -63,9 +63,9 @@ export class FollowersListComponent extends RestTable implements O .subscribe({ next: () => { // eslint-disable-next-line max-len - const message = prepareIcu($localize`Accepted {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`)( - { count: follows.length, followerName: this.buildFollowerName(follows[0]) }, - $localize`Follow requests accepted` + const message = formatICU( + $localize`Accepted {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`, + { count: follows.length, followerName: this.buildFollowerName(follows[0]) } ) this.notifier.success(message) @@ -78,9 +78,9 @@ export class FollowersListComponent extends RestTable implements O async rejectFollower (follows: ActorFollow[]) { // eslint-disable-next-line max-len - const message = prepareIcu($localize`Do you really want to reject {count, plural, =1 {{followerName} follow request?} other {{count} follow requests?}}`)( - { count: follows.length, followerName: this.buildFollowerName(follows[0]) }, - $localize`Do you really want to reject these follow requests?` + const message = formatICU( + $localize`Do you really want to reject {count, plural, =1 {{followerName} follow request?} other {{count} follow requests?}}`, + { count: follows.length, followerName: this.buildFollowerName(follows[0]) } ) const res = await this.confirmService.confirm(message, $localize`Reject`) @@ -90,9 +90,9 @@ export class FollowersListComponent extends RestTable implements O .subscribe({ next: () => { // eslint-disable-next-line max-len - const message = prepareIcu($localize`Rejected {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`)( - { count: follows.length, followerName: this.buildFollowerName(follows[0]) }, - $localize`Follow requests rejected` + const message = formatICU( + $localize`Rejected {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`, + { count: follows.length, followerName: this.buildFollowerName(follows[0]) } ) this.notifier.success(message) @@ -110,9 +110,9 @@ export class FollowersListComponent extends RestTable implements O message += '

' // eslint-disable-next-line max-len - message += prepareIcu($localize`Do you really want to delete {count, plural, =1 {{followerName} follow request?} other {{count} follow requests?}}`)( - icuParams, - $localize`Do you really want to delete these follow requests?` + message += formatICU( + $localize`Do you really want to delete {count, plural, =1 {{followerName} follow request?} other {{count} follow requests?}}`, + icuParams ) const res = await this.confirmService.confirm(message, $localize`Delete`) @@ -122,9 +122,9 @@ export class FollowersListComponent extends RestTable implements O .subscribe({ next: () => { // eslint-disable-next-line max-len - const message = prepareIcu($localize`Removed {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`)( - icuParams, - $localize`Follow requests removed` + const message = formatICU( + $localize`Removed {count, plural, =1 {{followerName} follow request} other {{count} follow requests}}`, + icuParams ) this.notifier.success(message) diff --git a/client/src/app/+admin/follows/following-list/follow-modal.component.ts b/client/src/app/+admin/follows/following-list/follow-modal.component.ts index 8f74e82a6..54b3cebc5 100644 --- a/client/src/app/+admin/follows/following-list/follow-modal.component.ts +++ b/client/src/app/+admin/follows/following-list/follow-modal.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' import { Notifier } from '@app/core' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' import { splitAndGetNotEmpty, UNIQUE_HOSTS_OR_HANDLE_VALIDATOR } from '@app/shared/form-validators/host-validators' import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' import { InstanceFollowService } from '@app/shared/shared-instance' @@ -62,9 +62,9 @@ export class FollowModalComponent extends FormReactive implements OnInit { .subscribe({ next: () => { this.notifier.success( - prepareIcu($localize`{count, plural, =1 {Follow request sent!} other {Follow requests sent!}}`)( - { count: hostsOrHandles.length }, - $localize`Follow request(s) sent!` + formatICU( + $localize`{count, plural, =1 {Follow request sent!} other {Follow requests sent!}}`, + { count: hostsOrHandles.length } ) ) diff --git a/client/src/app/+admin/follows/following-list/following-list.component.ts b/client/src/app/+admin/follows/following-list/following-list.component.ts index 71f2fbe66..6c8723c16 100644 --- a/client/src/app/+admin/follows/following-list/following-list.component.ts +++ b/client/src/app/+admin/follows/following-list/following-list.component.ts @@ -6,7 +6,7 @@ import { InstanceFollowService } from '@app/shared/shared-instance' import { ActorFollow } from '@shared/models' import { FollowModalComponent } from './follow-modal.component' import { DropdownAction } from '@app/shared/shared-main' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' @Component({ templateUrl: './following-list.component.html', @@ -64,9 +64,9 @@ export class FollowingListComponent extends RestTable implements O async removeFollowing (follows: ActorFollow[]) { const icuParams = { count: follows.length, entryName: this.buildFollowingName(follows[0]) } - const message = prepareIcu($localize`Do you really want to unfollow {count, plural, =1 {{entryName}?} other {{count} entries?}}`)( - icuParams, - $localize`Do you really want to unfollow these entries?` + const message = formatICU( + $localize`Do you really want to unfollow {count, plural, =1 {{entryName}?} other {{count} entries?}}`, + icuParams ) const res = await this.confirmService.confirm(message, $localize`Unfollow`) @@ -76,9 +76,9 @@ export class FollowingListComponent extends RestTable implements O .subscribe({ next: () => { // eslint-disable-next-line max-len - const message = prepareIcu($localize`You are not following {count, plural, =1 {{entryName} anymore.} other {these {count} entries anymore.}}`)( - icuParams, - $localize`You are not following them anymore.` + const message = formatICU( + $localize`You are not following {count, plural, =1 {{entryName} anymore.} other {these {count} entries anymore.}}`, + icuParams ) this.notifier.success(message) diff --git a/client/src/app/+admin/moderation/registration-list/registration-list.component.ts b/client/src/app/+admin/moderation/registration-list/registration-list.component.ts index 3ca1ceab8..35d9d13d7 100644 --- a/client/src/app/+admin/moderation/registration-list/registration-list.component.ts +++ b/client/src/app/+admin/moderation/registration-list/registration-list.component.ts @@ -2,7 +2,7 @@ import { SortMeta } from 'primeng/api' import { Component, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' import { AdvancedInputFilter } from '@app/shared/shared-forms' import { DropdownAction } from '@app/shared/shared-main' import { UserRegistration, UserRegistrationState } from '@shared/models' @@ -121,9 +121,9 @@ export class RegistrationListComponent extends RestTable impl const icuParams = { count: registrations.length, username: registrations[0].username } // eslint-disable-next-line max-len - const message = prepareIcu($localize`Do you really want to delete {count, plural, =1 {{username} registration request?} other {{count} registration requests?}}`)( - icuParams, - $localize`Do you really want to delete these registration requests?` + const message = formatICU( + $localize`Do you really want to delete {count, plural, =1 {{username} registration request?} other {{count} registration requests?}}`, + icuParams ) const res = await this.confirmService.confirm(message, $localize`Delete`) @@ -133,9 +133,9 @@ export class RegistrationListComponent extends RestTable impl .subscribe({ next: () => { // eslint-disable-next-line max-len - const message = prepareIcu($localize`Removed {count, plural, =1 {{username} registration request} other {{count} registration requests}}`)( - icuParams, - $localize`Registration requests removed` + const message = formatICU( + $localize`Removed {count, plural, =1 {{username} registration request} other {{count} registration requests}}`, + icuParams ) this.notifier.success(message) diff --git a/client/src/app/+admin/overview/comments/video-comment-list.component.ts b/client/src/app/+admin/overview/comments/video-comment-list.component.ts index 28efdc076..b77072665 100644 --- a/client/src/app/+admin/overview/comments/video-comment-list.component.ts +++ b/client/src/app/+admin/overview/comments/video-comment-list.component.ts @@ -7,7 +7,7 @@ import { DropdownAction } from '@app/shared/shared-main' import { BulkService } from '@app/shared/shared-moderation' import { VideoCommentAdmin, VideoCommentService } from '@app/shared/shared-video-comment' import { FeedFormat, UserRight } from '@shared/models' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' @Component({ selector: 'my-video-comment-list', @@ -146,9 +146,9 @@ export class VideoCommentListComponent extends RestTable imp .subscribe({ next: () => { this.notifier.success( - prepareIcu($localize`{count, plural, =1 {1 comment deleted.} other {{count} comments deleted.}}`)( - { count: commentArgs.length }, - $localize`${commentArgs.length} comment(s) deleted.` + formatICU( + $localize`{count, plural, =1 {1 comment deleted.} other {{count} comments deleted.}}`, + { count: commentArgs.length } ) ) diff --git a/client/src/app/+admin/overview/users/user-list/user-list.component.ts b/client/src/app/+admin/overview/users/user-list/user-list.component.ts index 19420b748..5d5abf6f4 100644 --- a/client/src/app/+admin/overview/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/overview/users/user-list/user-list.component.ts @@ -2,7 +2,7 @@ import { SortMeta } from 'primeng/api' import { Component, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { AuthService, ConfirmService, LocalStorageService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' -import { getAPIHost, prepareIcu } from '@app/helpers' +import { formatICU, getAPIHost } from '@app/helpers' import { AdvancedInputFilter } from '@app/shared/shared-forms' import { Actor, DropdownAction } from '@app/shared/shared-main' import { AccountMutedStatus, BlocklistService, UserBanModalComponent, UserModerationDisplayType } from '@app/shared/shared-moderation' @@ -210,9 +210,9 @@ export class UserListComponent extends RestTable implements OnInit { async unbanUsers (users: User[]) { const res = await this.confirmService.confirm( - prepareIcu($localize`Do you really want to unban {count, plural, =1 {1 user} other {{count} users}}?`)( - { count: users.length }, - $localize`Do you really want to unban ${users.length} users?` + formatICU( + $localize`Do you really want to unban {count, plural, =1 {1 user} other {{count} users}}?`, + { count: users.length } ), $localize`Unban` ) @@ -223,9 +223,9 @@ export class UserListComponent extends RestTable implements OnInit { .subscribe({ next: () => { this.notifier.success( - prepareIcu($localize`{count, plural, =1 {1 user unbanned.} other {{count} users unbanned.}}`)( - { count: users.length }, - $localize`${users.length} users unbanned.` + formatICU( + $localize`{count, plural, =1 {1 user unbanned.} other {{count} users unbanned.}}`, + { count: users.length } ) ) this.reloadData() @@ -252,9 +252,9 @@ export class UserListComponent extends RestTable implements OnInit { .subscribe({ next: () => { this.notifier.success( - prepareIcu($localize`{count, plural, =1 {1 user deleted.} other {{count} users deleted.}}`)( - { count: users.length }, - $localize`${users.length} users deleted.` + formatICU( + $localize`{count, plural, =1 {1 user deleted.} other {{count} users deleted.}}`, + { count: users.length } ) ) @@ -270,9 +270,9 @@ export class UserListComponent extends RestTable implements OnInit { .subscribe({ next: () => { this.notifier.success( - prepareIcu($localize`{count, plural, =1 {1 user email set as verified.} other {{count} user emails set as verified.}}`)( - { count: users.length }, - $localize`${users.length} users email set as verified.` + formatICU( + $localize`{count, plural, =1 {1 user email set as verified.} other {{count} user emails set as verified.}}`, + { count: users.length } ) ) diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts index ebf82ce16..e9c526193 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.ts +++ b/client/src/app/+admin/overview/videos/video-list.component.ts @@ -3,7 +3,7 @@ import { finalize } from 'rxjs/operators' import { Component, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { AuthService, ConfirmService, Notifier, RestPagination, RestTable } from '@app/core' -import { prepareIcu } from '@app/helpers' +import { formatICU } from '@app/helpers' import { AdvancedInputFilter } from '@app/shared/shared-forms' import { DropdownAction, Video, VideoService } from '@app/shared/shared-main' import { VideoBlockComponent, VideoBlockService } from '@app/shared/shared-moderation' @@ -219,9 +219,9 @@ export class VideoListComponent extends RestTable