web: use strings from @notesnook/intl in more places

This commit is contained in:
Abdullah Atta
2024-10-03 15:13:11 +05:00
committed by Abdullah Atta
parent bb53b0167b
commit 3e55492318
37 changed files with 1359 additions and 342 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -16,8 +16,8 @@
"@emotion/react": "11.11.1", "@emotion/react": "11.11.1",
"@hazae41/foras": "^2.1.4", "@hazae41/foras": "^2.1.4",
"@henrygd/queue": "^1.0.6", "@henrygd/queue": "^1.0.6",
"@lingui/core": "4.11.2", "@lingui/core": "4.11.4",
"@lingui/react": "4.11.2", "@lingui/react": "4.11.4",
"@mdi/js": "^7.2.96", "@mdi/js": "^7.2.96",
"@mdi/react": "^1.6.1", "@mdi/react": "^1.6.1",
"@notesnook-importer/core": "^2.1.1", "@notesnook-importer/core": "^2.1.1",
@@ -35,6 +35,7 @@
"@notesnook/web-clipper": "file:../../extensions/web-clipper", "@notesnook/web-clipper": "file:../../extensions/web-clipper",
"@react-pdf-viewer/core": "^3.12.0", "@react-pdf-viewer/core": "^3.12.0",
"@react-pdf-viewer/toolbar": "^3.12.0", "@react-pdf-viewer/toolbar": "^3.12.0",
"@streetwriters/kysely": "^0.27.4",
"@tanstack/react-query": "^4.36.1", "@tanstack/react-query": "^4.36.1",
"@tanstack/react-virtual": "^3.0.1", "@tanstack/react-virtual": "^3.0.1",
"@theme-ui/color": "^0.16.1", "@theme-ui/color": "^0.16.1",
@@ -59,7 +60,6 @@
"hash-wasm": "^4.9.0", "hash-wasm": "^4.9.0",
"hotkeys-js": "^3.8.3", "hotkeys-js": "^3.8.3",
"katex": "0.16.2", "katex": "0.16.2",
"@streetwriters/kysely": "^0.27.4",
"mac-scrollbar": "^0.13.5", "mac-scrollbar": "^0.13.5",
"marked": "^4.1.0", "marked": "^4.1.0",
"mutative": "^1.0.6", "mutative": "^1.0.6",
@@ -84,7 +84,6 @@
"react-virtuoso": "^4.6.2", "react-virtuoso": "^4.6.2",
"timeago.js": "4.0.2", "timeago.js": "4.0.2",
"tinycolor2": "^1.6.0", "tinycolor2": "^1.6.0",
"vite-plugin-commonjs": "^0.10.1",
"w3c-keyname": "^2.2.6", "w3c-keyname": "^2.2.6",
"web-streams-polyfill": "^3.1.1", "web-streams-polyfill": "^3.1.1",
"wouter": "2.12.1", "wouter": "2.12.1",

View File

@@ -34,7 +34,7 @@ import { ExportStream } from "../utils/streams/export-stream";
import { showToast } from "../utils/toast"; import { showToast } from "../utils/toast";
import { ConfirmDialog } from "../dialogs/confirm"; import { ConfirmDialog } from "../dialogs/confirm";
import { db } from "./db"; import { db } from "./db";
import { toAsyncIterator } from "@notesnook-importer/core"; import { toAsyncIterator } from "@notesnook-importer/core/dist/src/utils/stream";
import { saveAs } from "file-saver"; import { saveAs } from "file-saver";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
@@ -108,7 +108,7 @@ export async function exportNotes(
ConfirmDialog.show({ ConfirmDialog.show({
title: `Export failed`, title: `Export failed`,
message: result.stack || result.message, message: result.stack || result.message,
positiveButtonText: "Okay" positiveButtonText: strings.okay()
}); });
return false; return false;
} else { } else {
@@ -120,7 +120,7 @@ export async function exportNotes(
${result.errors.map((e, i) => `${i + 1}. ${e.message}`).join("\n")}` ${result.errors.map((e, i) => `${i + 1}. ${e.message}`).join("\n")}`
: "Export completed with 0 errors.", : "Export completed with 0 errors.",
positiveButtonText: "Okay" positiveButtonText: strings.okay()
}); });
return true; return true;
} }

View File

@@ -27,7 +27,6 @@ import { db } from "./db";
import { showToast } from "../utils/toast"; import { showToast } from "../utils/toast";
import Vault from "./vault"; import Vault from "./vault";
import { TaskManager } from "./task-manager"; import { TaskManager } from "./task-manager";
import { pluralize } from "@notesnook/common";
import { ConfirmDialog, showMultiDeleteConfirmation } from "../dialogs/confirm"; import { ConfirmDialog, showMultiDeleteConfirmation } from "../dialogs/confirm";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
@@ -52,7 +51,7 @@ async function moveNotesToTrash(ids: string[], confirm = true) {
title: strings.deletingItems("note", items.length), title: strings.deletingItems("note", items.length),
action: async (report) => { action: async (report) => {
report({ report({
text: `${strings.deleting()} ${strings.notes(items.length)}...` text: `${strings.inProgressAction("note", items.length, "deleting")}...`
}); });
await noteStore.delete(...items); await noteStore.delete(...items);
} }
@@ -75,9 +74,10 @@ async function moveNotebooksToTrash(ids: string[]) {
title: strings.deletingItems("notebook", ids.length), title: strings.deletingItems("notebook", ids.length),
action: async (report) => { action: async (report) => {
report({ report({
text: `${strings.deleting()} ${strings.itemsPlural( text: `${strings.inProgressAction(
"notebook", "notebook",
ids.length ids.length,
"deleting"
)}...` )}...`
}); });
await notebookStore.delete(...ids); await notebookStore.delete(...ids);
@@ -91,9 +91,9 @@ async function deleteAttachments(ids: string[]) {
if ( if (
!(await ConfirmDialog.show({ !(await ConfirmDialog.show({
title: strings.doAction("attachment", ids.length, "permanentlyDelete"), title: strings.doAction("attachment", ids.length, "permanentlyDelete"),
message: strings.permanentlyDeleteDesc("attachment", ids.length), message: strings.irreverisibleAction(),
negativeButtonText: "No", negativeButtonText: strings.no(),
positiveButtonText: "Yes" positiveButtonText: strings.yes()
})) }))
) )
return; return;
@@ -109,9 +109,10 @@ async function deleteAttachments(ids: string[]) {
if (!attachment) continue; if (!attachment) continue;
report({ report({
text: `${strings.deleting()} ${strings.itemsPlural( text: `${strings.inProgressAction(
"attachment", "attachment",
ids.length ids.length,
"deleting"
)}...`, )}...`,
current: i, current: i,
total: ids.length total: ids.length
@@ -135,9 +136,10 @@ async function moveRemindersToTrash(ids: string[]) {
title: strings.deletingItems("reminder", ids.length), title: strings.deletingItems("reminder", ids.length),
action: async (report) => { action: async (report) => {
report({ report({
text: `${strings.deleting()} ${strings.itemsPlural( text: `${strings.inProgressAction(
"reminder", "reminder",
ids.length ids.length,
"deleting"
)}...` )}...`
}); });
await reminderStore.delete(...ids); await reminderStore.delete(...ids);
@@ -159,7 +161,7 @@ async function deleteTags(ids: string[]) {
title: "Deleting tags", title: "Deleting tags",
action: async (report) => { action: async (report) => {
report({ report({
text: `Deleting ${pluralize(ids.length, "tag")}...` text: `${strings.inProgressAction("tag", ids.length, "deleting")}...`
}); });
for (const id of ids) { for (const id of ids) {
await db.tags.remove(id); await db.tags.remove(id);
@@ -170,7 +172,7 @@ async function deleteTags(ids: string[]) {
} }
}); });
showToast("success", `${pluralize(ids.length, "tag")} deleted.`); showToast("success", strings.deleted("tag", ids.length));
} }
export const Multiselect = { export const Multiselect = {

View File

@@ -213,8 +213,8 @@ export const notebookMenuItems: (
onClick: async () => { onClick: async () => {
const result = await ConfirmDialog.show({ const result = await ConfirmDialog.show({
title: `Delete ${pluralize(ids.length, "notebook")}?`, title: `Delete ${pluralize(ids.length, "notebook")}?`,
positiveButtonText: `Yes`, positiveButtonText: strings.yes(),
negativeButtonText: "No", negativeButtonText: strings.no(),
checks: { checks: {
deleteContainingNotes: { deleteContainingNotes: {
text: `Move all notes in ${ text: `Move all notes in ${

View File

@@ -65,24 +65,24 @@ import { TITLE_BAR_HEIGHT } from "../title-bar";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
const tools = [ const tools = [
{ key: "pin", property: "pinned", icon: Pin, label: "Pin" }, { key: "pin", property: "pinned", icon: Pin, label: strings.pin() },
{ {
key: "favorite", key: "favorite",
property: "favorite", property: "favorite",
icon: StarOutline, icon: StarOutline,
label: "Favorite" label: strings.favorite()
}, },
{ key: "lock", icon: Unlock, label: "Lock", property: "locked" }, { key: "lock", icon: Unlock, label: strings.lock(), property: "locked" },
{ {
key: "readonly", key: "readonly",
icon: Readonly, icon: Readonly,
label: "Readonly", label: strings.readOnly(),
property: "readonly" property: "readonly"
}, },
{ {
key: "local-only", key: "local-only",
icon: SyncOff, icon: SyncOff,
label: "Disable sync", label: strings.disableSync(),
property: "localOnly" property: "localOnly"
} }
] as const; ] as const;
@@ -96,12 +96,12 @@ type MetadataItem<T extends "dateCreated" | "dateEdited"> = {
const metadataItems = [ const metadataItems = [
{ {
key: "dateCreated", key: "dateCreated",
label: "Created at", label: strings.createdAt(),
value: (date) => getFormattedDate(date || Date.now()) value: (date) => getFormattedDate(date || Date.now())
} as MetadataItem<"dateCreated">, } as MetadataItem<"dateCreated">,
{ {
key: "dateEdited", key: "dateEdited",
label: "Last edited at", label: strings.lastEditedAt(),
value: (date) => (date ? getFormattedDate(date) : "never") value: (date) => (date ? getFormattedDate(date) : "never")
} as MetadataItem<"dateEdited"> } as MetadataItem<"dateEdited">
]; ];
@@ -251,7 +251,7 @@ function InternalLinks({ noteId }: { noteId: string }) {
mb: 1 mb: 1
}} }}
> >
{["Linked notes", "Referenced in"].map((title, index) => ( {[strings.linkedNotes(), strings.referencedIn()].map((title, index) => (
<Button <Button
key={title} key={title}
variant="secondary" variant="secondary"

View File

@@ -37,7 +37,6 @@ import { hashNavigate } from "../../navigation";
import { Multiselect } from "../../common/multi-select"; import { Multiselect } from "../../common/multi-select";
import { store } from "../../stores/reminder-store"; import { store } from "../../stores/reminder-store";
import { db } from "../../common/db"; import { db } from "../../common/db";
import { pluralize } from "@notesnook/common";
import { getFormattedReminderTime } from "@notesnook/common"; import { getFormattedReminderTime } from "@notesnook/common";
import { MenuItem } from "@notesnook/ui"; import { MenuItem } from "@notesnook/ui";
import { Reminder as ReminderType } from "@notesnook/core"; import { Reminder as ReminderType } from "@notesnook/core";
@@ -153,10 +152,10 @@ const menuItems: (reminder: ReminderType, items?: string[]) => MenuItem[] = (
icon: Trash.path, icon: Trash.path,
onClick: async () => { onClick: async () => {
ConfirmDialog.show({ ConfirmDialog.show({
title: `Delete ${pluralize(items.length, "reminder")}`, title: strings.doAction("reminder", items.length, "delete"),
message: `Are you sure you want to proceed? **This action is IRREVERSIBLE**.`, message: strings.irreverisibleAction(),
positiveButtonText: "Yes", positiveButtonText: strings.yes(),
negativeButtonText: "No" negativeButtonText: strings.no()
}).then((result) => { }).then((result) => {
result && Multiselect.moveRemindersToTrash(items); result && Multiselect.moveRemindersToTrash(items);
}); });

View File

@@ -73,18 +73,21 @@ export const AddNotebookDialog = DialogManager.register(
<Dialog <Dialog
testId="add-notebook-dialog" testId="add-notebook-dialog"
isOpen={true} isOpen={true}
title={props.edit ? "Edit Notebook" : "Create a Notebook"} title={props.edit ? strings.editNotebook() : strings.newNotebook()}
description={ description={
props.edit props.edit && notebook?.title
? `You are editing "${notebook?.title}".` ? strings.editNotebookDesc(notebook.title)
: "Notebooks are the best way to organize your notes." : strings.newNotebookDesc()
} }
onClose={() => onClose(false)} onClose={() => onClose(false)}
positiveButton={{ positiveButton={{
text: props.edit ? "Save" : "Create", text: props.edit ? strings.save() : strings.create(),
onClick: onSubmit onClick: onSubmit
}} }}
negativeButton={{ text: "Cancel", onClick: () => onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => onClose(false)
}}
> >
<Field <Field
defaultValue={title.current} defaultValue={title.current}

View File

@@ -153,12 +153,12 @@ export const AddReminderDialog = DialogManager.register(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={reminder ? "Edit reminder" : "Add a reminder"} title={reminder ? strings.editReminder() : strings.newReminder()}
testId="add-reminder-dialog" testId="add-reminder-dialog"
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
sx={{ fontFamily: "body" }} sx={{ fontFamily: "body" }}
positiveButton={{ positiveButton={{
text: reminder ? "Save" : "Add", text: reminder ? strings.save() : strings.add(),
disabled: disabled:
!title || !title ||
(mode !== Modes.ONCE && (mode !== Modes.ONCE &&
@@ -201,7 +201,10 @@ export const AddReminderDialog = DialogManager.register(
props.onClose(true); props.onClose(true);
} }
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
<Field <Field
id="title" id="title"
@@ -255,9 +258,7 @@ export const AddReminderDialog = DialogManager.register(
setSelectedDays([]); setSelectedDays([]);
}} }}
/> />
{strings.reminderModes[ {strings.reminderModes(m.id)}
m.id as keyof typeof strings.reminderModes
]()}
{m.premium && !isUserPremium && ( {m.premium && !isUserPremium && (
<Pro size={18} color="accent" sx={{ ml: 1 }} /> <Pro size={18} color="accent" sx={{ ml: 1 }} />
)} )}
@@ -299,9 +300,7 @@ export const AddReminderDialog = DialogManager.register(
: "paragraph" : "paragraph"
}} }}
> >
{strings.recurringModes[ {strings.recurringModes(mode.id)}
mode.id as keyof typeof strings.recurringModes
]()}
</Button> </Button>
))} ))}
</Flex> </Flex>

View File

@@ -28,7 +28,6 @@ import { db } from "../common/db";
import Dialog from "../components/dialog"; import Dialog from "../components/dialog";
import { useStore, store } from "../stores/tag-store"; import { useStore, store } from "../stores/tag-store";
import { store as notestore } from "../stores/note-store"; import { store as notestore } from "../stores/note-store";
import { useEditorStore } from "../stores/editor-store";
import { FilteredList } from "../components/filtered-list"; import { FilteredList } from "../components/filtered-list";
import { ItemReference, Tag } from "@notesnook/core"; import { ItemReference, Tag } from "@notesnook/core";
import { create } from "zustand"; import { create } from "zustand";
@@ -85,12 +84,12 @@ export const AddTagsDialog = DialogManager.register(function AddTagsDialog(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={"Add tags"} title={strings.addTags()}
description={`Add tags to multiple notes at once`} description={strings.addTagsDesc()}
onClose={() => onClose(false)} onClose={() => onClose(false)}
width={450} width={450}
positiveButton={{ positiveButton={{
text: "Done", text: strings.done(),
onClick: async () => { onClick: async () => {
for (const id of noteIds) { for (const id of noteIds) {
for (const item of useSelectionStore.getState().selected) { for (const item of useSelectionStore.getState().selected) {
@@ -106,7 +105,7 @@ export const AddTagsDialog = DialogManager.register(function AddTagsDialog(
} }
}} }}
negativeButton={{ negativeButton={{
text: "Cancel", text: strings.cancel(),
onClick: () => onClose(false) onClick: () => onClose(false)
}} }}
> >

View File

@@ -49,7 +49,6 @@ import {
Uploading Uploading
} from "../components/icons"; } from "../components/icons";
import NavigationItem from "../components/navigation-menu/navigation-item"; import NavigationItem from "../components/navigation-menu/navigation-item";
import { pluralize } from "@notesnook/common";
import { db } from "../common/db"; import { db } from "../common/db";
import { Attachment } from "../components/attachment"; import { Attachment } from "../components/attachment";
import { ScopedThemeProvider } from "../components/theme-provider"; import { ScopedThemeProvider } from "../components/theme-provider";
@@ -510,8 +509,8 @@ const Sidebar = memo(
await ConfirmDialog.show({ await ConfirmDialog.show({
title: strings.clearCacheConfirm(), title: strings.clearCacheConfirm(),
message: strings.clearCacheConfirmDesc(), message: strings.clearCacheConfirmDesc(),
negativeButtonText: "No", negativeButtonText: strings.no(),
positiveButtonText: "Yes" positiveButtonText: strings.yes()
}) })
) { ) {
await db.fs().clear(); await db.fs().clear();

View File

@@ -43,19 +43,20 @@ export const BackupPasswordDialog = DialogManager.register(
<Dialog <Dialog
isOpen={true} isOpen={true}
testId="password-dialog" testId="password-dialog"
title={"Encrypted backup"} title={strings.encryptedBackup()}
description={ description={strings.encryptedBackupDesc()}
"Please enter the password to decrypt and restore this backup."
}
onClose={() => onClose(false)} onClose={() => onClose(false)}
positiveButton={{ positiveButton={{
form: "backupPasswordForm", form: "backupPasswordForm",
type: "submit", type: "submit",
loading: isLoading, loading: isLoading,
disabled: isLoading, disabled: isLoading,
text: "Restore" text: strings.restore()
}}
negativeButton={{
text: strings.cancel(),
onClick: () => onClose(false)
}} }}
negativeButton={{ text: "Cancel", onClick: () => onClose(false) }}
> >
<Box <Box
id="backupPasswordForm" id="backupPasswordForm"

View File

@@ -146,39 +146,35 @@ export const ConfirmDialog = DialogManager.register(function ConfirmDialog<
export function showMultiDeleteConfirmation(length: number) { export function showMultiDeleteConfirmation(length: number) {
return ConfirmDialog.show({ return ConfirmDialog.show({
title: strings.doAction("item", length, "delete"), title: strings.doAction("item", length, "delete"),
message: `These items will be **kept in your Trash for ${ message: strings.moveToTrashDesc(
db.settings.getTrashCleanupInterval() || 7 db.settings.getTrashCleanupInterval() || 7
} days** after which they will be permanently deleted.`, ),
positiveButtonText: "Yes", positiveButtonText: strings.yes(),
negativeButtonText: "No" negativeButtonText: strings.no()
}); });
} }
export function showMultiPermanentDeleteConfirmation(length: number) { export function showMultiPermanentDeleteConfirmation(length: number) {
return ConfirmDialog.show({ return ConfirmDialog.show({
title: `Permanently delete ${pluralize(length, "item")}?`, title: strings.doAction("item", length, "permanentlyDelete"),
message: message: strings.irreverisibleAction(),
"These items will be **permanently deleted**. This is IRREVERSIBLE.", positiveButtonText: strings.yes(),
positiveButtonText: "Yes", negativeButtonText: strings.no()
negativeButtonText: "No"
}); });
} }
export async function showLogoutConfirmation() { export async function showLogoutConfirmation() {
return await ConfirmDialog.show({ return await ConfirmDialog.show({
title: `Logout?`, title: strings.logout(),
message: message: strings.logoutConfirmation(),
"Are you sure you want to log out and clear all data stored on THIS DEVICE?", positiveButtonText: strings.yes(),
positiveButtonText: "Yes", negativeButtonText: strings.no(),
negativeButtonText: "No",
warnings: (await db.hasUnsyncedChanges()) warnings: (await db.hasUnsyncedChanges())
? [ ? [strings.unsyncedChangesWarning()]
"You have unsynced notes. Take a backup or sync your notes to avoid losing critical data."
]
: [], : [],
checks: { checks: {
backup: { backup: {
text: "Take a backup before logging out?", text: strings.backupDataBeforeLogout(),
default: true default: true
} }
} }
@@ -189,8 +185,8 @@ export function showClearSessionsConfirmation() {
return ConfirmDialog.show({ return ConfirmDialog.show({
title: strings.logoutAllOtherDevices(), title: strings.logoutAllOtherDevices(),
message: strings.logoutAllOtherDevicesDescription(), message: strings.logoutAllOtherDevicesDescription(),
positiveButtonText: "Yes", positiveButtonText: strings.yes(),
negativeButtonText: "No" negativeButtonText: strings.no()
}); });
} }
@@ -205,7 +201,7 @@ export async function showUpdateAvailableNotice({
title: strings.newVersion(), title: strings.newVersion(),
subtitle: strings.newVersionAvailable(version), subtitle: strings.newVersionAvailable(version),
changelog, changelog,
action: { text: `Update now`, onClick: () => downloadUpdate() } action: { text: strings.updateNow(), onClick: () => downloadUpdate() }
}); });
} }

View File

@@ -36,14 +36,17 @@ export const CreateColorDialog = DialogManager.register(
<Dialog <Dialog
testId="new-color-dialog" testId="new-color-dialog"
isOpen={true} isOpen={true}
title={"Create a new color"} title={strings.newColor()}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
form: "colorForm", form: "colorForm",
type: "submit", type: "submit",
text: "Create" text: strings.create()
}}
negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }}
> >
<Box <Box
as="form" as="form"

View File

@@ -48,13 +48,13 @@ export const EditProfilePictureDialog = DialogManager.register(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={"Edit profile picture"} title={strings.editProfilePicture()}
description="Your profile data is stored 100% end-to-end encrypted." description={strings.editProfilePictureDesc()}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
loading: isLoading, loading: isLoading,
disabled: isLoading, disabled: isLoading,
text: "Save", text: strings.save(),
onClick: async () => { onClick: async () => {
setIsLoading(true); setIsLoading(true);
try { try {
@@ -79,7 +79,10 @@ export const EditProfilePictureDialog = DialogManager.register(
} }
} }
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
<Flex <Flex
sx={{ sx={{

View File

@@ -65,18 +65,19 @@ export const EmailChangeDialog = DialogManager.register(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={"Change account email"} title={strings.changeEmail()}
description={ description={strings.changeEmailDesc()}
"Your account email will be changed without affecting your subscription or any other settings."
}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
text: "Next", text: strings.next(),
disabled: isLoading, disabled: isLoading,
loading: isLoading, loading: isLoading,
form: "changeEmailForm" form: "changeEmailForm"
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
<Flex <Flex
id="changeEmailForm" id="changeEmailForm"

View File

@@ -66,10 +66,8 @@ export const EmailVerificationDialog = DialogManager.register(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={"Confirm your email"} title={strings.confirmEmail()}
description={ description={strings.confirmEmailDesc()}
"Check your spam folder if you haven't received an email yet."
}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
text: canSendAgain || isSending ? "Resend" : `Resend (${resetTimer})`, text: canSendAgain || isSending ? "Resend" : `Resend (${resetTimer})`,
@@ -88,7 +86,7 @@ export const EmailVerificationDialog = DialogManager.register(
disabled: isSending || !canSendAgain disabled: isSending || !canSendAgain
}} }}
negativeButton={{ negativeButton={{
text: "Cancel", text: strings.cancel(),
onClick: () => props.onClose(true), onClick: () => props.onClose(true),
disabled: isSending disabled: isSending
}} }}
@@ -103,7 +101,7 @@ export const EmailVerificationDialog = DialogManager.register(
</Text> </Text>
<Accordion <Accordion
isClosed isClosed
title={"What do I do if I am not getting the email?"} title={strings.confirmEmailTroubleshoot()}
sx={{ sx={{
mt: 2, mt: 2,
bg: "var(--background-secondary)", bg: "var(--background-secondary)",
@@ -111,9 +109,9 @@ export const EmailVerificationDialog = DialogManager.register(
}} }}
> >
<Text variant={"body"} px={1} pb={1}> <Text variant={"body"} px={1} pb={1}>
{strings.emailConfirmationNotice()[0]}{" "} {strings.confirmEmailTroubleshootNotice()[0]}{" "}
<b>{strings.emailConfirmationNotice()[1]}</b>{" "} <b>{strings.confirmEmailTroubleshootNotice()[1]}</b>{" "}
{strings.emailConfirmationNotice()[2]}. {strings.confirmEmailTroubleshootNotice()[2]}.
</Text> </Text>
</Accordion> </Accordion>
</Flex> </Flex>

View File

@@ -24,6 +24,7 @@ import { Flex, Image, Label, Text } from "@theme-ui/components";
import { formatBytes } from "@notesnook/common"; import { formatBytes } from "@notesnook/common";
import { compressImage } from "../utils/image-compressor"; import { compressImage } from "../utils/image-compressor";
import { BaseDialogProps, DialogManager } from "../common/dialog-manager"; import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
import { strings } from "@notesnook/intl";
export type ImagePickerDialogProps = BaseDialogProps<false | File[]> & { export type ImagePickerDialogProps = BaseDialogProps<false | File[]> & {
images: File[]; images: File[];
@@ -82,10 +83,13 @@ export const ImagePickerDialog = DialogManager.register(
isOpen={true} isOpen={true}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
text: "Insert", text: strings.insert(),
onClick: () => props.onClose(images) onClick: () => props.onClose(images)
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
{selectedImage && ( {selectedImage && (
<Flex sx={{ flexDirection: "column", alignItems: "center", mt: 4 }}> <Flex sx={{ flexDirection: "column", alignItems: "center", mt: 4 }}>

View File

@@ -53,7 +53,10 @@ export const ItemDialog = DialogManager.register(function ItemDialog(
text: props.title text: props.title
}} }}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
<Box <Box
as="form" as="form"

View File

@@ -31,6 +31,7 @@ import { Authenticator, OnNextFunction } from "./types";
import { ErrorText } from "../../components/error-text"; import { ErrorText } from "../../components/error-text";
import { AuthenticatorType } from "@notesnook/core"; import { AuthenticatorType } from "@notesnook/core";
import { BaseDialogProps, DialogManager } from "../../common/dialog-manager"; import { BaseDialogProps, DialogManager } from "../../common/dialog-manager";
import { strings } from "@notesnook/intl";
type MultifactorDialogProps = BaseDialogProps<boolean> & { type MultifactorDialogProps = BaseDialogProps<boolean> & {
primaryMethod?: AuthenticatorType; primaryMethod?: AuthenticatorType;
@@ -56,7 +57,7 @@ export const MultifactorDialog = DialogManager.register(
positiveButton={ positiveButton={
step.next step.next
? { ? {
text: "Continue", text: strings.continue(),
form: "2faForm" form: "2faForm"
} }
: null : null
@@ -64,7 +65,7 @@ export const MultifactorDialog = DialogManager.register(
negativeButton={ negativeButton={
step.cancellable step.cancellable
? { ? {
text: "Cancel", text: strings.cancel(),
onClick: () => props.onClose(false) onClick: () => props.onClose(false)
} }
: null : null

View File

@@ -23,6 +23,7 @@ import { steps } from "./steps";
import { ErrorText } from "../../components/error-text"; import { ErrorText } from "../../components/error-text";
import { AuthenticatorType } from "@notesnook/core"; import { AuthenticatorType } from "@notesnook/core";
import { BaseDialogProps, DialogManager } from "../../common/dialog-manager"; import { BaseDialogProps, DialogManager } from "../../common/dialog-manager";
import { strings } from "@notesnook/intl";
type RecoveryCodesDialogProps = BaseDialogProps<boolean> & { type RecoveryCodesDialogProps = BaseDialogProps<boolean> & {
primaryMethod: AuthenticatorType; primaryMethod: AuthenticatorType;
@@ -41,7 +42,7 @@ export const RecoveryCodesDialog = DialogManager.register(
description={step.description} description={step.description}
width={500} width={500}
positiveButton={{ positiveButton={{
text: "Okay", text: strings.okay(),
onClick: () => onClose(true) onClick: () => onClose(true)
}} }}
> >

View File

@@ -86,10 +86,10 @@ export const MigrationDialog = DialogManager.register(function MigrationDialog(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={"There was an error"} title={strings.migrationFailed()}
description={""} description={""}
positiveButton={{ positiveButton={{
text: "Try again", text: strings.tryAgain(),
onClick: startMigration onClick: startMigration
}} }}
> >
@@ -118,17 +118,15 @@ export const MigrationDialog = DialogManager.register(function MigrationDialog(
<Dialog <Dialog
width={500} width={500}
isOpen={true} isOpen={true}
title={"Save a backup of your notes"} title={strings.migrationSaveBackup()}
description={""} description={""}
positiveButton={{ positiveButton={{
text: "Save & continue", text: strings.saveAndContinue(),
onClick: startMigration onClick: startMigration
}} }}
> >
<Text as="p" variant={"body"}> <Text as="p" variant={"body"}>
{ {strings.migrationSaveBackupDesc()}
"Thank you for updating Notesnook! We'll be applying some minor changes for a better note taking experience."
}
</Text> </Text>
</Dialog> </Dialog>
); );

View File

@@ -129,14 +129,12 @@ export const MoveNoteDialog = DialogManager.register(function MoveNoteDialog({
<Dialog <Dialog
testId="move-note-dialog" testId="move-note-dialog"
isOpen={true} isOpen={true}
title={"Select notebooks"} title={strings.selectNotebooks()}
description={`Use ${ description={strings.selectNotebooksDesktopDesc(isMac() ? "Cmd" : "Ctrl")}
isMac() ? "cmd" : "ctrl"
}+click to select multiple notebooks`}
onClose={() => _onClose(false)} onClose={() => _onClose(false)}
width={450} width={450}
positiveButton={{ positiveButton={{
text: "Done", text: strings.done(),
onClick: async () => { onClick: async () => {
const { selected } = useSelectionStore.getState(); const { selected } = useSelectionStore.getState();
for (const item of selected) { for (const item of selected) {
@@ -167,7 +165,7 @@ export const MoveNoteDialog = DialogManager.register(function MoveNoteDialog({
} }
}} }}
negativeButton={{ negativeButton={{
text: "Cancel", text: strings.cancel(),
onClick: () => _onClose(false) onClick: () => _onClose(false)
}} }}
> >

View File

@@ -56,7 +56,9 @@ export const NoteLinkingDialog = DialogManager.register(
return ( return (
<Dialog <Dialog
isOpen={true} isOpen={true}
title={attributes ? "Edit internal link" : "Link to note"} title={
attributes ? strings.editInternalLink() : strings.newInternalLink()
}
width={500} width={500}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
onOpen={async () => { onOpen={async () => {
@@ -65,7 +67,7 @@ export const NoteLinkingDialog = DialogManager.register(
); );
}} }}
positiveButton={{ positiveButton={{
text: "Insert link", text: attributes ? strings.done() : strings.insertLink(),
disabled: !selectedNote, disabled: !selectedNote,
onClick: () => onClick: () =>
selectedNote selectedNote
@@ -75,7 +77,10 @@ export const NoteLinkingDialog = DialogManager.register(
}) })
: null : null
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
noScroll noScroll
> >
<Flex variant="columnFill" sx={{ mx: 3, overflow: "hidden" }}> <Flex variant="columnFill" sx={{ mx: 3, overflow: "hidden" }}>

View File

@@ -24,6 +24,7 @@ import Field, { FieldProps } from "../components/field";
import { Checkbox, Label } from "@theme-ui/components"; import { Checkbox, Label } from "@theme-ui/components";
import { mdToHtml } from "../utils/md"; import { mdToHtml } from "../utils/md";
import { BaseDialogProps, DialogManager } from "../common/dialog-manager"; import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
import { strings } from "@notesnook/intl";
type Check = { text: string; default?: boolean }; type Check = { text: string; default?: boolean };
export type PasswordDialogProps< export type PasswordDialogProps<
@@ -55,11 +56,11 @@ const PasswordDialog = DialogManager.register(function PasswordDialog<
positiveButton={{ positiveButton={{
form: "passwordForm", form: "passwordForm",
type: "submit", type: "submit",
text: "Submit", text: strings.submit(),
loading: isLoading, loading: isLoading,
disabled: isLoading disabled: isLoading
}} }}
negativeButton={{ text: "Cancel", onClick: () => onClose(false) }} negativeButton={{ text: strings.cancel(), onClick: () => onClose(false) }}
> >
<Box <Box
id="passwordForm" id="passwordForm"

View File

@@ -21,6 +21,7 @@ import { useRef } from "react";
import Field from "../components/field"; import Field from "../components/field";
import Dialog from "../components/dialog"; import Dialog from "../components/dialog";
import { BaseDialogProps, DialogManager } from "../common/dialog-manager"; import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
import { strings } from "@notesnook/intl";
export type PromptDialogProps = BaseDialogProps<false | string> & { export type PromptDialogProps = BaseDialogProps<false | string> & {
title: string; title: string;
@@ -39,10 +40,13 @@ export const PromptDialog = DialogManager.register(function PromptDialog(
description={props.description} description={props.description}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
positiveButton={{ positiveButton={{
text: "Done", text: strings.submit(),
onClick: () => props.onClose(inputRef.current?.value || "") onClick: () => props.onClose(inputRef.current?.value || "")
}} }}
negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} negativeButton={{
text: strings.cancel(),
onClick: () => props.onClose(false)
}}
> >
<Field <Field
inputRef={inputRef} inputRef={inputRef}

View File

@@ -72,7 +72,7 @@ export const ReminderPreviewDialog = DialogManager.register(
description={reminder.description} description={reminder.description}
onClose={() => props.onClose(false)} onClose={() => props.onClose(false)}
negativeButton={{ negativeButton={{
text: "Close", text: strings.close(),
onClick: () => props.onClose(false) onClick: () => props.onClose(false)
}} }}
> >

View File

@@ -30,7 +30,7 @@ export const BehaviourSettings: SettingsGroup[] = [
{ {
key: "general", key: "general",
section: "behaviour", section: "behaviour",
header: "General", header: strings.general(),
isHidden: () => !isUserPremium(), isHidden: () => !isUserPremium(),
settings: [ settings: [
{ {

View File

@@ -145,14 +145,14 @@ export function SubscriptionStatus() {
title: "Cancel subscription?", title: "Cancel subscription?",
message: message:
"Cancelling your subscription will automatically downgrade you to the Basic plan at the end of your billing period. You will have to resubscribe to continue using the Pro features.", "Cancelling your subscription will automatically downgrade you to the Basic plan at the end of your billing period. You will have to resubscribe to continue using the Pro features.",
negativeButtonText: "No", negativeButtonText: strings.no(),
positiveButtonText: "Yes" positiveButtonText: strings.yes()
}); });
if (cancelSubscription) { if (cancelSubscription) {
await TaskManager.startTask({ await TaskManager.startTask({
type: "modal", type: "modal",
title: "Cancelling your subscription", title: "Cancelling your subscription",
subtitle: "Please wait...", subtitle: strings.pleaseWait() + "...",
action: () => db.subscriptions.cancel() action: () => db.subscriptions.cancel()
}) })
.catch((e) => showToast("error", e.message)) .catch((e) => showToast("error", e.message))
@@ -172,14 +172,14 @@ export function SubscriptionStatus() {
title: "Request refund?", title: "Request refund?",
message: message:
"You will only be issued a refund if you are eligible as per our refund policy. Your account will be immediately downgraded to Basic and your funds will be transferred to your account within 24 hours.", "You will only be issued a refund if you are eligible as per our refund policy. Your account will be immediately downgraded to Basic and your funds will be transferred to your account within 24 hours.",
negativeButtonText: "No", negativeButtonText: strings.no(),
positiveButtonText: "Yes" positiveButtonText: strings.yes()
}); });
if (refundSubscription) { if (refundSubscription) {
await TaskManager.startTask({ await TaskManager.startTask({
type: "modal", type: "modal",
title: "Requesting refund for your subscription", title: "Requesting refund for your subscription",
subtitle: "Please wait...", subtitle: strings.pleaseWait() + "...",
action: () => db.subscriptions.refund() action: () => db.subscriptions.refund()
}) })
.catch((e) => showToast("error", e.message)) .catch((e) => showToast("error", e.message))

View File

@@ -217,7 +217,7 @@ function ThemesList() {
}} }}
> >
{themes.isInitialLoading ? ( {themes.isInitialLoading ? (
<Loader title={"Loading themes..."} /> <Loader title={strings.loadingThemes()} />
) : ( ) : (
<VirtualizedGrid <VirtualizedGrid
columns={2} columns={2}

View File

@@ -17,12 +17,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { strings } from "@notesnook/intl";
import { ServersConfiguration } from "./components/servers-configuration"; import { ServersConfiguration } from "./components/servers-configuration";
import { SettingsGroup } from "./types"; import { SettingsGroup } from "./types";
export const ServersSettings: SettingsGroup[] = [ export const ServersSettings: SettingsGroup[] = [
{ {
header: "Servers configuration", header: strings.serversConfiguration(),
key: "servers", key: "servers",
section: "servers", section: "servers",
settings: [ settings: [

View File

@@ -31,7 +31,7 @@ export const VaultSettings: SettingsGroup[] = [
{ {
key: "vault", key: "vault",
section: "vault", section: "vault",
header: "Vault", header: strings.vault(),
settings: [ settings: [
{ {
key: "create-vault", key: "create-vault",

View File

@@ -41,12 +41,12 @@ export const ThemeDetailsDialog = DialogManager.register(
isOpen={true} isOpen={true}
onClose={() => onClose(false)} onClose={() => onClose(false)}
positiveButton={{ positiveButton={{
text: `Set as default`, text: strings.setAsDefault(),
onClick: () => onClose(true), onClick: () => onClose(true),
disabled: isThemeCurrentlyApplied(theme.id) disabled: isThemeCurrentlyApplied(theme.id)
}} }}
negativeButton={{ negativeButton={{
text: "Close", text: strings.cancel(),
onClick: () => onClose(false) onClick: () => onClose(false)
}} }}
> >

View File

@@ -571,32 +571,28 @@ function AccountRecovery(props: BaseAuthComponentProps<"recover">) {
function getTexts(formData: MFAFormData) { function getTexts(formData: MFAFormData) {
return { return {
app: { app: {
subtitle: subtitle: strings.mfaAuthAppSubtitle(),
"Please confirm your identity by entering the authentication code from your authenticator app.", instructions: strings.mfaAuthAppInstructions(),
instructions: `Open the two-factor authentication (TOTP) app to view your authentication code.`, selector: strings.mfaAuthAppSelector(),
selector: `Don't have access to your authenticator app?`, label: strings.enterSixDigitCode()
label: "Enter 6-digit code"
}, },
email: { email: {
subtitle: subtitle: strings.mfaEmailSubtitle(),
"Please confirm your identity by entering the authentication code sent to your email address.", instructions: strings.mfaEmailInstructions(),
instructions: `It may take a minute to receive your code.`, selector: strings.mfaEmailSelector(),
selector: `Don't have access to your email address?`, label: strings.enterSixDigitCode()
label: "Enter 6-digit code"
}, },
sms: { sms: {
subtitle: `Please confirm your identity by entering the authentication code sent to ${ subtitle: strings.mfaSmsSubtitle(formData.phoneNumber),
formData.phoneNumber || "your registered phone number." instructions: strings.mfaSmsInstructions(),
}.`, selector: strings.mfaSmsSelector(),
instructions: `It may take a minute to receive your code.`, label: strings.enterSixDigitCode()
selector: `Don't have access to your phone number?`,
label: "Enter 6-digit code"
}, },
recoveryCode: { recoveryCode: {
subtitle: `Please confirm your identity by entering a recovery code.`, subtitle: strings.mfaRecoveryCodeSubtitle(),
instructions: "", instructions: "",
selector: `Don't have your recovery codes?`, selector: strings.mfaRecoveryCodeSelector(),
label: "Enter recovery code" label: strings.enterRecoveryCode()
} }
}; };
} }

View File

@@ -564,7 +564,9 @@ function NotebookHeader({
sx={{ borderRadius: 100, width: 30, height: 30 }} sx={{ borderRadius: 100, width: 30, height: 30 }}
mr={1} mr={1}
p={0} p={0}
title={isShortcut ? "Remove shortcut" : "Create shortcut"} title={
isShortcut ? strings.removeShortcut() : strings.createShortcut()
}
onClick={() => addToShortcuts(notebook)} onClick={() => addToShortcuts(notebook)}
> >
{isShortcut ? ( {isShortcut ? (

View File

@@ -523,7 +523,7 @@ function Final(_props: BaseRecoveryComponentProps<"final">) {
}, []); }, []);
if (!isReady && !isSessionExpired) if (!isReady && !isSessionExpired)
return <Loader text="" title={"Finalizing. Please wait..."} />; return <Loader text="" title={strings.loading() + "..."} />;
return ( return (
<RecoveryForm <RecoveryForm

View File

@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { PluginOption, defineConfig } from "vite"; import { PluginOption, defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc"; import react from "@vitejs/plugin-react-swc";
import svgrPlugin from "vite-plugin-svgr"; import svgrPlugin from "vite-plugin-svgr";
import commonjs from "vite-plugin-commonjs";
import envCompatible from "vite-plugin-env-compatible"; import envCompatible from "vite-plugin-env-compatible";
import { VitePWA } from "vite-plugin-pwa"; import { VitePWA } from "vite-plugin-pwa";
import autoprefixer from "autoprefixer"; import autoprefixer from "autoprefixer";
@@ -128,9 +127,6 @@ export default defineConfig({
} }
}, },
plugins: [ plugins: [
commonjs({
filter: (id) => (id.includes("notesnook/packages/intl") ? true : false)
}),
...(isAnalyzing ...(isAnalyzing
? [ ? [
visualizer({ visualizer({