mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-18 21:34:28 -04:00
Use named tokens in frontend translate function
This commit is contained in:
@@ -143,7 +143,7 @@ class BookshelfFooter extends Component {
|
||||
|
||||
<div>
|
||||
<div className={styles.label}>
|
||||
{selectedCount} Author(s) Selected
|
||||
{translate('CountAuthorsSelected', { selectedCount })}
|
||||
</div>
|
||||
|
||||
<SpinnerButton
|
||||
|
||||
@@ -152,7 +152,7 @@ class CustomFormat extends Component {
|
||||
isOpen={this.state.isDeleteCustomFormatModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteCustomFormat')}
|
||||
message={translate('DeleteCustomFormatMessageText', [name])}
|
||||
message={translate('DeleteCustomFormatMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
isSpinning={isDeleting}
|
||||
onConfirm={this.onConfirmDeleteCustomFormat}
|
||||
|
||||
@@ -115,7 +115,7 @@ class Specification extends Component {
|
||||
isOpen={this.state.isDeleteSpecificationModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteCondition')}
|
||||
message={translate('DeleteConditionMessageText', [name])}
|
||||
message={translate('DeleteConditionMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteSpecification}
|
||||
onCancel={this.onDeleteSpecificationModalClose}
|
||||
|
||||
@@ -113,7 +113,7 @@ class DownloadClient extends Component {
|
||||
isOpen={this.state.isDeleteDownloadClientModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteDownloadClient')}
|
||||
message={translate('DeleteDownloadClientMessageText', [name])}
|
||||
message={translate('DeleteDownloadClientMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteDownloadClient}
|
||||
onCancel={this.onDeleteDownloadClientModalClose}
|
||||
|
||||
+1
-1
@@ -180,7 +180,7 @@ function ManageDownloadClientsEditModalContent(
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<div className={styles.selected}>
|
||||
{translate('CountDownloadClientsSelected', [selectedCount])}
|
||||
{translate('CountDownloadClientsSelected', { selectedCount })}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
+3
-3
@@ -286,9 +286,9 @@ function ManageDownloadClientsModalContent(
|
||||
isOpen={isDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteSelectedDownloadClients')}
|
||||
message={translate('DeleteSelectedDownloadClientsMessageText', [
|
||||
selectedIds.length,
|
||||
])}
|
||||
message={translate('DeleteSelectedDownloadClientsMessageText', {
|
||||
count: selectedIds.length,
|
||||
})}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={onConfirmDelete}
|
||||
onCancel={onDeleteModalClose}
|
||||
|
||||
@@ -107,7 +107,7 @@ class ImportList extends Component {
|
||||
isOpen={this.state.isDeleteImportListModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteImportList')}
|
||||
message={translate('DeleteImportListMessageText', [name])}
|
||||
message={translate('DeleteImportListMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteImportList}
|
||||
onCancel={this.onDeleteImportListModalClose}
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ function ManageImportListsEditModalContent(
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<div className={styles.selected}>
|
||||
{translate('CountImportListsSelected', [selectedCount])}
|
||||
{translate('CountImportListsSelected', { selectedCount })}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
+3
-3
@@ -283,9 +283,9 @@ function ManageImportListsModalContent(
|
||||
isOpen={isDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteSelectedImportLists')}
|
||||
message={translate('DeleteSelectedImportListsMessageText', [
|
||||
selectedIds.length,
|
||||
])}
|
||||
message={translate('DeleteSelectedImportListsMessageText', {
|
||||
count: selectedIds.length,
|
||||
})}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={onConfirmDelete}
|
||||
onCancel={onDeleteModalClose}
|
||||
|
||||
@@ -152,7 +152,7 @@ class Indexer extends Component {
|
||||
isOpen={this.state.isDeleteIndexerModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteIndexer')}
|
||||
message={translate('DeleteIndexerMessageText', [name])}
|
||||
message={translate('DeleteIndexerMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteIndexer}
|
||||
onCancel={this.onDeleteIndexerModalClose}
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ function ManageIndexersEditModalContent(
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<div className={styles.selected}>
|
||||
{translate('CountIndexersSelected', [selectedCount])}
|
||||
{translate('CountIndexersSelected', { selectedCount })}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -281,9 +281,9 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
|
||||
isOpen={isDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteSelectedIndexers')}
|
||||
message={translate('DeleteSelectedIndexersMessageText', [
|
||||
selectedIds.length,
|
||||
])}
|
||||
message={translate('DeleteSelectedIndexersMessageText', {
|
||||
count: selectedIds.length,
|
||||
})}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={onConfirmDelete}
|
||||
onCancel={onDeleteModalClose}
|
||||
|
||||
@@ -95,7 +95,7 @@ class RootFolder extends Component {
|
||||
isOpen={this.state.isDeleteRootFolderModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteRootFolder')}
|
||||
message={translate('DeleteRootFolderMessageText', [name])}
|
||||
message={translate('DeleteRootFolderMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteRootFolder}
|
||||
onCancel={this.onDeleteRootFolderModalClose}
|
||||
|
||||
@@ -227,7 +227,7 @@ class Notification extends Component {
|
||||
isOpen={this.state.isDeleteNotificationModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteNotification')}
|
||||
message={translate('DeleteNotificationMessageText', [name])}
|
||||
message={translate('DeleteNotificationMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteNotification}
|
||||
onCancel={this.onDeleteNotificationModalClose}
|
||||
|
||||
@@ -144,7 +144,7 @@ class MetadataProfile extends Component {
|
||||
isOpen={this.state.isDeleteMetadataProfileModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteMetadataProfile')}
|
||||
message={translate('DeleteMetadataProfileMessageText', [name])}
|
||||
message={translate('DeleteMetadataProfileMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
isSpinning={isDeleting}
|
||||
onConfirm={this.onConfirmDeleteMetadataProfile}
|
||||
|
||||
@@ -162,7 +162,7 @@ class QualityProfile extends Component {
|
||||
isOpen={this.state.isDeleteQualityProfileModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteQualityProfile')}
|
||||
message={translate('DeleteQualityProfileMessageText', [name])}
|
||||
message={translate('DeleteQualityProfileMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
isSpinning={isDeleting}
|
||||
onConfirm={this.onConfirmDeleteQualityProfile}
|
||||
|
||||
@@ -138,7 +138,7 @@ class BackupRow extends Component {
|
||||
isOpen={isConfirmDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteBackup')}
|
||||
message={translate('DeleteBackupMessageText', [name])}
|
||||
message={translate('DeleteBackupMessageText', { name })}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeletePress}
|
||||
onCancel={this.onConfirmDeleteModalClose}
|
||||
|
||||
@@ -146,7 +146,7 @@ class RestoreBackupModalContent extends Component {
|
||||
|
||||
<ModalBody>
|
||||
{
|
||||
!!id && `Would you like to restore the backup '${name}'?`
|
||||
!!id && translate('WouldYouLikeToRestoreBackup', { name })
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -25,18 +25,19 @@ export async function fetchTranslations(): Promise<boolean> {
|
||||
|
||||
export default function translate(
|
||||
key: string,
|
||||
args?: (string | number | boolean)[]
|
||||
tokens?: Record<string, string | number | boolean>
|
||||
) {
|
||||
if (!(key in translations)) {
|
||||
console.debug(key);
|
||||
}
|
||||
|
||||
const translation = translations[key] || key;
|
||||
|
||||
if (args) {
|
||||
return translation.replace(/\{(\d+)\}/g, (match, index) => {
|
||||
return String(args[index]) ?? match;
|
||||
if (tokens) {
|
||||
// Fallback to the old behaviour for translations not yet updated to use named tokens
|
||||
Object.values(tokens).forEach((value, index) => {
|
||||
tokens[index] = value;
|
||||
});
|
||||
|
||||
return translation.replace(/\{([a-z0-9]+?)\}/gi, (match, tokenMatch) =>
|
||||
String(tokens[tokenMatch] ?? match)
|
||||
);
|
||||
}
|
||||
|
||||
return translation;
|
||||
|
||||
Reference in New Issue
Block a user