From 71c45e0c55b0437bfa0e2651f573de5afae8cd47 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 7 Apr 2026 23:07:07 +0300 Subject: [PATCH] feat(i18n): extract untranslated frontend strings --- backend/locales/en.json | 212 +++++++++++++++++- frontend/src/App.vue | 2 +- .../src/components/ApiKeyCreateDialog.vue | 2 +- .../src/components/ApiKeyRevokeDialog.vue | 2 +- frontend/src/components/AssetDeleteDialog.vue | 2 +- frontend/src/components/AssetRenameDialog.vue | 4 +- frontend/src/components/AuthLoginPanel.vue | 6 +- frontend/src/components/ChangePwdDialog.vue | 4 +- frontend/src/components/CheckUpdateDialog.vue | 2 +- frontend/src/components/EditorMarkdown.vue | 26 +-- .../EditorMarkdownConfigOverlay.vue | 6 +- .../EditorMarkdownUserSettingsOverlay.vue | 6 +- frontend/src/components/FileManager.vue | 22 +- .../src/components/FolderCreateDialog.vue | 2 +- .../src/components/FolderDeleteDialog.vue | 2 +- .../src/components/FolderRenameDialog.vue | 4 +- frontend/src/components/GroupCreateDialog.vue | 2 +- frontend/src/components/GroupDeleteDialog.vue | 2 +- frontend/src/components/GroupEditOverlay.vue | 82 +++---- frontend/src/components/HeaderNav.vue | 8 +- frontend/src/components/HeaderSearch.vue | 18 +- frontend/src/components/IconPickerDialog.vue | 27 ++- frontend/src/components/NavEditMenu.vue | 30 +-- frontend/src/components/PageActionsCol.vue | 54 ++--- frontend/src/components/PageDataDialog.vue | 20 +- frontend/src/components/PageDeleteDialog.vue | 2 +- frontend/src/components/PageHeader.vue | 34 +-- frontend/src/components/PageNewMenu.vue | 18 +- frontend/src/components/PageSourceOverlay.vue | 2 +- .../src/components/RerenderPageDialog.vue | 2 +- frontend/src/components/SetupTfaDialog.vue | 2 +- .../src/components/SiteActivateDialog.vue | 2 +- frontend/src/components/SiteCreateDialog.vue | 2 +- frontend/src/components/SiteDeleteDialog.vue | 2 +- frontend/src/components/SocialSharingMenu.vue | 10 +- frontend/src/components/TreeBrowserDialog.vue | 8 +- .../components/UploadPendingAssetsDialog.vue | 2 +- .../src/components/UserChangePwdDialog.vue | 4 +- frontend/src/components/UserCreateDialog.vue | 4 +- frontend/src/components/UserDefaultsMenu.vue | 4 +- frontend/src/components/UserEditOverlay.vue | 6 +- .../src/components/WebhookDeleteDialog.vue | 2 +- frontend/src/components/WebhookEditDialog.vue | 6 +- frontend/src/components/WelcomeOverlay.vue | 6 +- frontend/src/layouts/MainLayout.vue | 26 +-- frontend/src/pages/AdminApi.vue | 4 +- frontend/src/pages/AdminAuth.vue | 4 +- frontend/src/pages/AdminBlocks.vue | 6 +- frontend/src/pages/AdminEditors.vue | 8 +- frontend/src/pages/AdminExtensions.vue | 2 +- frontend/src/pages/AdminFlags.vue | 6 +- frontend/src/pages/AdminGeneral.vue | 14 +- frontend/src/pages/AdminGroups.vue | 2 +- frontend/src/pages/AdminInstances.vue | 2 +- frontend/src/pages/AdminLocale.vue | 4 +- frontend/src/pages/AdminLogin.vue | 8 +- frontend/src/pages/AdminMail.vue | 6 +- frontend/src/pages/AdminMetrics.vue | 4 +- frontend/src/pages/AdminNavigation.vue | 6 +- frontend/src/pages/AdminPages.vue | 50 +++-- frontend/src/pages/AdminPagesVisualize.vue | 14 +- frontend/src/pages/AdminScheduler.vue | 10 +- frontend/src/pages/AdminSearch.vue | 6 +- frontend/src/pages/AdminSecurity.vue | 2 +- frontend/src/pages/AdminStorage.vue | 8 +- frontend/src/pages/AdminSystem.vue | 6 +- frontend/src/pages/AdminTags.vue | 4 +- frontend/src/pages/AdminTheme.vue | 10 +- frontend/src/pages/AdminUtilities.vue | 2 +- frontend/src/pages/AdminWebhooks.vue | 2 +- frontend/src/pages/ErrorGeneric.vue | 4 +- frontend/src/pages/Index.vue | 20 +- frontend/src/pages/ProfileAuth.vue | 6 +- frontend/src/pages/ProfileAvatar.vue | 4 +- frontend/src/pages/ProfileInfo.vue | 2 +- frontend/src/pages/Search.vue | 10 +- 76 files changed, 575 insertions(+), 352 deletions(-) diff --git a/backend/locales/en.json b/backend/locales/en.json index 09d1461554..d0287fd335 100644 --- a/backend/locales/en.json +++ b/backend/locales/en.json @@ -60,6 +60,7 @@ "admin.api.revokedHint": "This key has been revoked and can no longer be used.", "admin.api.subtitle": "Manage keys to access the API", "admin.api.title": "API Access", + "admin.api.switchStateFailed": "Failed to switch API state.", "admin.api.toggleStateDisabledSuccess": "API has been disabled successfully.", "admin.api.toggleStateEnabledSuccess": "API has been enabled successfully.", "admin.approval.title": "Approvals", @@ -109,12 +110,16 @@ "admin.auth.strategyStateLocked": "and cannot be disabled.", "admin.auth.subtitle": "Configure the authentication settings of your wiki", "admin.auth.title": "Authentication", + "admin.auth.deleteStrategy": "Delete Strategy", + "admin.auth.saveFailed": "Failed to save authentication configuration.", "admin.auth.vendor": "Vendor", "admin.auth.vendorWebsite": "Website", "admin.blocks.add": "Add Block", "admin.blocks.builtin": "Built-in", "admin.blocks.custom": "Custom", + "admin.blocks.fetchFailed": "Failed to fetch blocks state.", "admin.blocks.isEnabled": "Enabled", + "admin.blocks.saveFailed": "Failed to save blocks state.", "admin.blocks.saveSuccess": "Blocks state saved successfully.", "admin.blocks.subtitle": "Manage dynamic components available for use inside pages.", "admin.blocks.title": "Content Blocks", @@ -182,6 +187,9 @@ "admin.editors.markdownName": "Markdown Editor", "admin.editors.redirectDescription": "Create redirections to other pages / external links.", "admin.editors.redirectName": "Redirection", + "admin.editors.fetchFailed": "Failed to fetch editors state.", + "admin.editors.invalidConfigCall": "Invalid call to config:", + "admin.editors.saveFailed": "Failed to save editors state.", "admin.editors.saveSuccess": "Editors state saved successfully.", "admin.editors.subtitle": "Manage editors and their configuration", "admin.editors.title": "Editors", @@ -209,6 +217,8 @@ "admin.flags.experimental.label": "Experimental Features", "admin.flags.getTokenHint": "Copy your current authentication token for use in GraphQL API testing.", "admin.flags.getTokenLabel": "Get Current Token", + "admin.flags.tokenCopyFailed": "Failed to copy current token to clipboard.", + "admin.flags.tokenCopySuccess": "Current token copied to clipboard.", "admin.flags.saveSuccess": "Flags have been updated successfully.", "admin.flags.sqlLog.hint": "Log all queries made to the database to console.", "admin.flags.sqlLog.label": "SQL Query Logging", @@ -251,6 +261,7 @@ "admin.general.displaySiteTitleHint": "Should the site title be displayed next to the logo? If your logo isn't square and contain your brand name, turn this option off.", "admin.general.favicon": "Favicon", "admin.general.faviconHint": "Favicon image file, in SVG, PNG, JPG, WEBP or GIF format. Must be a square image.", + "admin.general.faviconUploadFailed": "Failed to upload site favicon.", "admin.general.faviconUploadSuccess": "Site Favicon uploaded successfully.", "admin.general.features": "Features", "admin.general.footerCopyright": "Footer / Copyright", @@ -260,6 +271,7 @@ "admin.general.logo": "Logo", "admin.general.logoUpl": "Site Logo", "admin.general.logoUplHint": "Logo image file, in SVG, PNG, JPG, WEBP or GIF format.", + "admin.general.logoUploadFailed": "Failed to upload site logo.", "admin.general.logoUploadSuccess": "Site logo uploaded successfully.", "admin.general.pageCasing": "Case Sensitive Paths", "admin.general.pageCasingHint": "Treat paths with different casing as distinct pages.", @@ -273,6 +285,7 @@ "admin.general.reasonForChangeOff": "Off", "admin.general.reasonForChangeOptional": "Optional", "admin.general.reasonForChangeRequired": "Required", + "admin.general.saveFailed": "Failed to save general configuration.", "admin.general.saveSuccess": "Site configuration saved successfully.", "admin.general.searchAllowFollow": "Allow Search Engines to Follow Links", "admin.general.searchAllowFollowHint": "This sets the meta-robots property to follow or nofollow.", @@ -319,8 +332,11 @@ "admin.groups.exportRules": "Export Rules", "admin.groups.exportRulesNoneError": "This group has no rule to export!", "admin.groups.filterUsers": "Filter...", + "admin.groups.fetchDetailsFailed": "Failed to fetch group details.", + "admin.groups.fetchUsersFailed": "Failed to fetch group users.", "admin.groups.general": "General", "admin.groups.importFailed": "Something went wrong while importing this file. Making sure it is a valid rules JSON file.", + "admin.groups.invalidRulesFormat": "Invalid rules format.", "admin.groups.importModeAdd": "Add to Existing", "admin.groups.importModeReplace": "Replace All", "admin.groups.importModeText": "Do you want to replace all existing rules with these ones or add these rules to the existing ones?", @@ -328,6 +344,7 @@ "admin.groups.importRules": "Import Rules", "admin.groups.importSuccess": "Rules imported successfully!", "admin.groups.info": "Group Info", + "admin.groups.newRule": "New Rule", "admin.groups.name": "Group Name", "admin.groups.nameHint": "Name of the group", "admin.groups.overview": "Overview", @@ -338,7 +355,45 @@ "admin.groups.redirectOnLoginHint": "The path / URL where the user will be redirected upon successful login. Leave empty to use the site-defined value.", "admin.groups.redirectOnLogout": "Redirect on Logout", "admin.groups.redirectOnLogoutHint": "The path / URL where the user will be redirected upon logout. Leave empty to use the site-defined value.", + "admin.groups.loadFailed": "Failed to load groups state.", "admin.groups.refreshSuccess": "Groups refreshed successfully.", + "admin.groups.permissions.accessAdminHint": "Can access the administration area.", + "admin.groups.permissions.manageUsersHint": "Can create and manage users, except users with administrative permissions.", + "admin.groups.permissions.manageGroupsHint": "Can create and manage groups, assign permissions, and manage page rules, except manage:system.", + "admin.groups.permissions.manageNavigationHint": "Can manage site navigation.", + "admin.groups.permissions.manageThemeHint": "Can modify site theme settings.", + "admin.groups.permissions.manageSitesHint": "Can create and manage sites.", + "admin.groups.permissions.manageSystemHint": "Can manage and access everything. Root administrator.", + "admin.groups.permissions.readPagesTitle": "Read Pages", + "admin.groups.permissions.readPagesHint": "Can view and search pages.", + "admin.groups.permissions.writePagesTitle": "Write Pages", + "admin.groups.permissions.writePagesHint": "Can create and edit pages.", + "admin.groups.permissions.reviewPagesTitle": "Review Pages", + "admin.groups.permissions.reviewPagesHint": "Can review and approve edits submitted by users.", + "admin.groups.permissions.managePagesTitle": "Manage Pages", + "admin.groups.permissions.managePagesHint": "Can move existing pages to other locations the user has write access to.", + "admin.groups.permissions.deletePagesTitle": "Delete Pages", + "admin.groups.permissions.deletePagesHint": "Can delete existing pages.", + "admin.groups.permissions.useCssTitle": "Use CSS", + "admin.groups.permissions.useCssHint": "Can insert CSS styles in pages.", + "admin.groups.permissions.useJavaScriptTitle": "Use JavaScript", + "admin.groups.permissions.useJavaScriptHint": "Can insert JavaScript in pages.", + "admin.groups.permissions.viewPageSourceTitle": "View Page Source", + "admin.groups.permissions.viewPageSourceHint": "Can view page source.", + "admin.groups.permissions.viewPageHistoryTitle": "View Page History", + "admin.groups.permissions.viewPageHistoryHint": "Can view previous versions of pages.", + "admin.groups.permissions.viewAssetsTitle": "View Assets", + "admin.groups.permissions.viewAssetsHint": "Can view and use assets, such as images and files, in pages.", + "admin.groups.permissions.uploadAssetsTitle": "Upload Assets", + "admin.groups.permissions.uploadAssetsHint": "Can upload new assets, such as images and files.", + "admin.groups.permissions.manageAssetsTitle": "Manage Assets", + "admin.groups.permissions.manageAssetsHint": "Can edit and delete existing assets, such as images and files.", + "admin.groups.permissions.readCommentsTitle": "Read Comments", + "admin.groups.permissions.readCommentsHint": "Can view page comments.", + "admin.groups.permissions.writeCommentsTitle": "Write Comments", + "admin.groups.permissions.writeCommentsHint": "Can post new comments on pages.", + "admin.groups.permissions.manageCommentsTitle": "Manage Comments", + "admin.groups.permissions.manageCommentsHint": "Can edit and delete existing page comments.", "admin.groups.ruleAllow": "Allow", "admin.groups.ruleDeny": "Deny", "admin.groups.ruleForceAllow": "Force Allow", @@ -371,9 +426,11 @@ "admin.instances.activeListeners": "Active Listeners", "admin.instances.firstSeen": "First Seen", "admin.instances.lastSeen": "Last Seen", + "admin.instances.loadFailed": "Failed to load instances list.", "admin.instances.subtitle": "View a list of active instances", "admin.instances.title": "Instances", "admin.locale.active": "Active Locales", + "admin.locale.activeHint": "The list of locale packs currently enabled for this site.", "admin.locale.activeNamespaces": "Active Namespaces", "admin.locale.autoUpdate.hint": "Automatically download updates to this locale as they become available.", "admin.locale.autoUpdate.hintWithNS": "Automatically download updates to all namespaced locales enabled below.", @@ -401,11 +458,13 @@ "admin.locale.settings": "Locale Settings", "admin.locale.sideload": "Sideload Locale Package", "admin.locale.sideloadHelp": "If you are not connected to the internet or cannot download locale files using the method above, you can instead sideload packages manually by uploading them below.", + "admin.locale.saveSuccess": "Locale settings saved successfully.", "admin.locale.subtitle": "Set localization options for your wiki", "admin.locale.title": "Locale", "admin.logging.title": "Logging", "admin.login.background": "Background Image", "admin.login.backgroundHint": "Specify an image to use as the login background. PNG and JPG are supported, 1920x1080 recommended. Leave empty for default.", + "admin.login.bgUploadFailed": "Failed to upload login background image.", "admin.login.bgUploadSuccess": "Login background image uploaded successfully.", "admin.login.bypassScreen": "Bypass Login Screen", "admin.login.bypassScreenHint": "Should the user be redirected automatically to the first authentication provider. Has no effect if the first provider is a username/password provider type.", @@ -418,6 +477,7 @@ "admin.login.logoutRedirectHint": "Optionally redirect the user to a specific page when he/she logouts. This can be overridden at the group level.", "admin.login.providers": "Login Providers", "admin.login.providersVisbleWarning": "Note that you can always temporarily show all hidden providers by adding ?all=1 to the url. This is useful to login as local admin while hiding it from normal users.", + "admin.login.saveFailed": "Failed to save login configuration.", "admin.login.saveSuccess": "Login configuration saved successfully.", "admin.login.subtitle": "Configure the login user experience of your wiki site", "admin.login.title": "Login", @@ -435,6 +495,7 @@ "admin.mail.dkimPrivateKeyHint": "Private key for the selector in PEM format", "admin.mail.dkimUse": "Use DKIM", "admin.mail.dkimUseHint": "Should DKIM be used when sending emails.", + "admin.mail.fetchConfigFailed": "Failed to fetch mail configuration.", "admin.mail.saveSuccess": "Configuration saved successfully.", "admin.mail.sendTestSuccess": "A test email was sent successfully.", "admin.mail.sender": "Sender", @@ -472,6 +533,7 @@ "admin.metrics.endpoint": "The metrics endpoint can be scraped at {endpoint}", "admin.metrics.endpointWarning": "Note that this override any page at this path.", "admin.metrics.refreshSuccess": "Metrics endpoint state has been refreshed.", + "admin.metrics.switchStateFailed": "Failed to switch metrics endpoint state.", "admin.metrics.subtitle": "Manage the Prometheus metrics endpoint", "admin.metrics.title": "Metrics", "admin.metrics.toggleStateDisabledSuccess": "Metrics endpoint disabled successfully.", @@ -506,6 +568,7 @@ "admin.navigation.navType.searchQuery": "Search Query", "admin.navigation.noItemsText": "Click the Add button to add your first navigation item.", "admin.navigation.noSelectionText": "Select a navigation item on the left.", + "admin.navigation.refreshSuccess": "Navigation has been refreshed.", "admin.navigation.saveSuccess": "Navigation saved successfully.", "admin.navigation.selectPageButton": "Select Page...", "admin.navigation.sourceLocale": "Source Locale", @@ -517,7 +580,25 @@ "admin.navigation.untitled": "Untitled {kind}", "admin.navigation.visibilityMode.all": "Visible to everyone", "admin.navigation.visibilityMode.restricted": "Visible to select groups...", + "admin.pages.locale": "Locale", + "admin.pages.localeAll": "All Locales", + "admin.pages.none": "No pages to display.", + "admin.pages.publishState": "Publish State", + "admin.pages.publishStateAll": "All Publishing States", + "admin.pages.publishStatePublished": "Published", + "admin.pages.publishStateUnpublished": "Not Published", + "admin.pages.recycleBin": "Recycle Bin", + "admin.pages.refreshSuccess": "Page list has been refreshed.", + "admin.pages.searchPlaceholder": "Search Pages...", + "admin.pages.subtitle": "Manage pages", "admin.pages.title": "Pages", + "admin.pages.visualize": "Visualize", + "admin.pages.visualizeEmpty": "Looks like there's no data yet to graph!", + "admin.pages.visualizeModeHierarchicalRadial": "Hierarchical Radial", + "admin.pages.visualizeModeRelationalRadial": "Relational Radial", + "admin.pages.visualizeModeTree": "Hierarchical Tree", + "admin.pages.visualizeSubtitle": "Dendrogram representation of your pages", + "admin.pages.visualizeTitle": "Visualize Pages", "admin.rendering.subtitle": "Configure the content rendering pipeline", "admin.rendering.title": "Rendering", "admin.scheduler.active": "Active", @@ -535,9 +616,12 @@ "admin.scheduler.failed": "Failed", "admin.scheduler.failedNone": "There are no recently failed job to display.", "admin.scheduler.interrupted": "Interrupted", + "admin.scheduler.loadFailed": "Failed to load scheduler jobs.", "admin.scheduler.pending": "Pending", "admin.scheduler.result": "Result", "admin.scheduler.retryJob": "Retry Job", + "admin.scheduler.cancelJobFailed": "Failed to cancel job.", + "admin.scheduler.retryJobFailed": "Failed to retry job.", "admin.scheduler.retryJobSuccess": "Job has been rescheduled and will execute shortly.", "admin.scheduler.schedule": "Schedule", "admin.scheduler.scheduled": "Scheduled", @@ -560,9 +644,12 @@ "admin.search.highlighting": "Enable Term Highlighting", "admin.search.highlightingHint": "Whether to show the highlighted terms in search results. There is a slight performance impact when enabled.", "admin.search.indexRebuildSuccess": "Index rebuilt successfully.", + "admin.search.loadFailed": "Failed to load search engine state.", "admin.search.listRefreshSuccess": "List of search engines has been refreshed.", "admin.search.rebuildIndex": "Rebuild Index", + "admin.search.rebuildFailed": "Failed to rebuild search index.", "admin.search.rebuildInitSuccess": "A search index rebuild has been initiated and will start shortly.", + "admin.search.saveFailed": "Failed to save search engine configuration.", "admin.search.saveSuccess": "Search engine configuration saved successfully", "admin.search.searchEngine": "Search Engine", "admin.search.subtitle": "Configure the search capabilities of your wiki", @@ -602,6 +689,7 @@ "admin.security.maxUploadSize": "Max Upload Size", "admin.security.maxUploadSizeHint": "The maximum size for a single file. Final value in base 2.", "admin.security.maxUploadSizeSuffix": "bytes", + "admin.security.saveFailed": "Failed to save security configuration.", "admin.security.saveSuccess": "Security configuration updated successfully.", "admin.security.scanSVG": "Scan and Sanitize SVG Uploads", "admin.security.scanSVGHint": "Should SVG uploads be scanned for vulnerabilities and stripped of any potentially unsafe content.", @@ -689,6 +777,7 @@ "admin.storage.contentTypeLargeFilesThreshold": "Size Threshold", "admin.storage.contentTypeOthers": "Others", "admin.storage.contentTypeOthersHint": "Any other file types that don't match the other categories.", + "admin.storage.loadFailed": "Failed to load storage targets.", "admin.storage.contentTypePages": "Pages", "admin.storage.contentTypePagesHint": "Page content source, in Markdown, HTML or JSON format depending on the editor.", "admin.storage.contentTypes": "Content Types", @@ -786,6 +875,9 @@ "admin.system.checkUpdate": "Check / Upgrade", "admin.system.checkingForUpdates": "Checking for Updates...", "admin.system.client": "Client", + "admin.system.copyInfoFailed": "Failed to copy system info.", + "admin.system.copyInfoSuccess": "System info copied successfully.", + "admin.system.copySystemInfo": "Copy System Info", "admin.system.clientCookies": "Cookies Support", "admin.system.clientCookiesHint": "Whether cookies are enabled on this browser.", "admin.system.clientLanguage": "Primary Language", @@ -883,6 +975,7 @@ "admin.theme.fonts": "Fonts", "admin.theme.headHtmlInjection": "Head HTML Injection", "admin.theme.headHtmlInjectionHint": "HTML code to be injected just before the closing head tag. Usually for script tags.", + "admin.theme.fetchFailed": "Failed to fetch theme configuration.", "admin.theme.headerColor": "Header Color", "admin.theme.headerColorHint": "The background color for the site top header. Does not apply to the administration area.", "admin.theme.iconset": "Icon Set", @@ -894,6 +987,7 @@ "admin.theme.reduceMotion": "Reduce Motion", "admin.theme.reduceMotionHint": "Disable most site animations. This setting is automatically enforced when the reduced motion flag is enabled on the user OS.", "admin.theme.resetDefaults": "Reset Defaults", + "admin.theme.saveFailed": "Failed to save theme configuration.", "admin.theme.saveSuccess": "Theme configuration saved successfully!", "admin.theme.secondaryColor": "Secondary Color", "admin.theme.secondaryColorHint": "The alternate color for secondary action buttons and for some other elements.", @@ -937,6 +1031,8 @@ "admin.users.dateFormat": "Date Format", "admin.users.dateFormatHint": "How dates should be formatted when displayed to the user.", "admin.users.defaults": "Manage User Defaults", + "admin.users.defaultsLoadFailed": "Failed to load user defaults.", + "admin.users.defaultsSaveFailed": "Failed to save user defaults.", "admin.users.defaultsSaveSuccess": "User defaults saved successfully.", "admin.users.delete": "Delete User", "admin.users.deleteConfirmForeignNotice": "Note that you cannot delete a user that already created content. You must instead either deactivate the user or delete all content that was created by that user.", @@ -951,6 +1047,7 @@ "admin.users.emailInvalid": "Email address is invalid.", "admin.users.emailMissing": "Email address is missing.", "admin.users.extendedMetadata": "Extended Metadata", + "admin.users.fetchDetailsFailed": "Failed to fetch user details.", "admin.users.groupAlreadyAssigned": "User is already assigned to this group.", "admin.users.groupAssign": "Assign", "admin.users.groupAssignNotice": "Note that you cannot assign users to the Administrators or Guests groups from this panel.", @@ -1054,6 +1151,7 @@ "admin.utilities.contentSubtitle": "Various tools for pages", "admin.utilities.contentTitle": "Content", "admin.utilities.disconnectWS": "Disconnect WebSocket Sessions", + "admin.utilities.disconnectWSFailed": "Failed to disconnect WS connections.", "admin.utilities.disconnectWSHint": "Force all active websocket connections to be closed.", "admin.utilities.disconnectWSSuccess": "All active websocket connections have been terminated.", "admin.utilities.export": "Export", @@ -1092,6 +1190,7 @@ "admin.webhooks.deleteConfirmWarn": "This action cannot be undone!", "admin.webhooks.deleteSuccess": "Webhook deleted successfully.", "admin.webhooks.edit": "Edit Webhook", + "admin.webhooks.fetchConfigFailed": "Failed to fetch webhook configuration.", "admin.webhooks.eventCreatePage": "Create a new page", "admin.webhooks.eventDeleteAsset": "Delete an asset", "admin.webhooks.eventDeleteComment": "Delete a comment", @@ -1164,6 +1263,7 @@ "auth.errors.passwordTooShort": "Password is too short.", "auth.errors.passwordsNotMatch": "Passwords do not match.", "auth.errors.register": "One or more fields are invalid.", + "auth.errors.unexpectedResponse": "Unexpected authentication response.", "auth.errors.tfaMissing": "Missing or incomplete security code.", "auth.errors.tooManyAttempts": "Too many attempts!", "auth.errors.tooManyAttemptsMsg": "You've made too many failed attempts in a short period of time, please try again {time}.", @@ -1178,6 +1278,7 @@ "auth.forgotPasswordLink": "Forgot Password", "auth.forgotPasswordLoading": "Requesting password reset...", "auth.forgotPasswordSubtitle": "Enter your email address to receive the instructions to reset your password:", + "auth.forgotPasswordUnavailable": "Forgot password is not implemented yet.", "auth.forgotPasswordSuccess": "Check your emails for password reset instructions!", "auth.forgotPasswordTitle": "Forgot your password", "auth.genericError": "Authentication is unavailable.", @@ -1236,6 +1337,7 @@ "common.actions.discardChanges": "Discard Changes", "common.actions.download": "Download", "common.actions.duplicate": "Duplicate", + "common.actions.email": "Email", "common.actions.edit": "Edit", "common.actions.exit": "Exit", "common.actions.fetch": "Fetch", @@ -1244,6 +1346,8 @@ "common.actions.goback": "Go Back", "common.actions.howItWorks": "How it works", "common.actions.insert": "Insert", + "common.actions.pick": "Pick...", + "common.actions.viewAll": "View All", "common.actions.login": "Login", "common.actions.manage": "Manage", "common.actions.move": "Move", @@ -1306,6 +1410,7 @@ "common.duration.years": "Year(s)", "common.error.generic.hint": "Oops, something went wrong...", "common.error.generic.title": "Unexpected Error", + "common.error.notImplemented": "Not implemented yet.", "common.error.notfound.hint": "That page doesn't exist or is not available.", "common.error.notfound.title": "Not Found", "common.error.title": "Error", @@ -1314,10 +1419,15 @@ "common.error.unexpected": "An unexpected error occurred.", "common.error.unknownsite.hint": "There's no wiki site at this host.", "common.error.unknownsite.title": "Unknown Site", + "common.field.basic": "Basic", "common.field.createdOn": "Created On", + "common.field.created": "Created", "common.field.id": "ID", + "common.field.json": "JSON", "common.field.lastUpdated": "Last Updated", "common.field.name": "Name", + "common.field.none": "None", + "common.field.path": "Path", "common.field.task": "Task", "common.field.title": "Title", "common.footerCopyright": "© {year} {company}. All rights reserved.", @@ -1332,6 +1442,7 @@ "common.header.delete": "Delete", "common.header.duplicate": "Duplicate", "common.header.edit": "Edit", + "common.header.editNavigation": "Edit Navigation", "common.header.history": "History", "common.header.home": "Home", "common.header.imagesFiles": "Images & Files", @@ -1343,6 +1454,8 @@ "common.header.newPage": "New Page", "common.header.pageActions": "Page Actions", "common.header.profile": "Profile", + "common.header.bookmarks": "Bookmarks", + "common.header.browse": "Browse", "common.header.search": "Search...", "common.header.searchClose": "Close", "common.header.searchCopyLink": "Copy Search Link", @@ -1352,8 +1465,10 @@ "common.header.searchNoResult": "No pages matching your query.", "common.header.searchResultsCount": "Found {total} results", "common.header.siteMap": "Site Map", + "common.header.switchLocale": "Switch Locale", "common.header.view": "View", "common.header.viewSource": "View Source", + "common.locale.loadFailed": "Failed to load locale strings for {locale}.", "common.license.alr": "All Rights Reserved", "common.license.cc0": "Public Domain", "common.license.ccby": " Creative Commons Attribution License", @@ -1381,10 +1496,14 @@ "common.page.global": "Global", "common.page.id": "ID {id}", "common.page.lastEditedBy": "Last edited by", + "common.page.lastModifiedOn": "Last modified on", "common.page.loading": "Loading Page...", + "common.page.noEditorSpecified": "No editor specified.", + "common.page.print": "Print", "common.page.printFormat": "Print Format", "common.page.private": "Private", "common.page.published": "Published", + "common.page.rate": "Rate this page", "common.page.returnNormalView": "Return to Normal View", "common.page.share": "Share", "common.page.tags": "Tags", @@ -1392,6 +1511,7 @@ "common.page.toc": "Table of Contents", "common.page.unpublished": "Unpublished", "common.page.unpublishedWarning": "This page is not published.", + "common.page.watch": "Watch Page", "common.page.versionId": "Version ID {id}", "common.page.viewingSource": "Viewing source of page {path}", "common.page.viewingSourceVersion": "Viewing source as of {date} of page {path}", @@ -1494,7 +1614,16 @@ "editor.markup.header": "Header", "editor.markup.headerLevel": "Header {level}", "editor.markup.heading": "Heading {level}", + "editor.markup.increaseHeaderLevel": "Increase Header Level", "editor.markup.inlineCode": "Inline Code", + "editor.markup.fromClipboard": "From Clipboard...", + "editor.markup.fromFileManager": "From File Manager...", + "editor.markup.fromRemoteURL": "From Remote URL...", + "editor.markup.clipboardError": "Unable to read from clipboard.", + "editor.markup.clipboardReadDenied": "Not allowed to read clipboard.", + "editor.markup.clipboardUnsupported": "No supported content found in the clipboard.", + "editor.markup.fetchConfigFailed": "Failed to fetch markdown editor configuration.", + "editor.markup.fetchUserSettingsFailed": "Failed to fetch markdown editor settings.", "editor.markup.insertAssets": "Insert Assets", "editor.markup.insertBlock": "Insert Block", "editor.markup.insertCodeBlock": "Insert Code Block", @@ -1509,9 +1638,11 @@ "editor.markup.insertVideoAudio": "Insert Video / Audio", "editor.markup.italic": "Italic", "editor.markup.keyboardKey": "Keyboard Key", + "editor.markup.markdown": "Markdown", "editor.markup.markdownFormattingHelp": "Markdown Formatting Help", "editor.markup.noSelectionError": "Text must be selected first!", "editor.markup.orderedList": "Ordered List", + "editor.markup.decreaseHeaderLevel": "Decrease Header Level", "editor.markup.strikethrough": "Strikethrough", "editor.markup.subscript": "Subscript", "editor.markup.superscript": "Superscript", @@ -1519,8 +1650,12 @@ "editor.markup.taskList": "Task List", "editor.markup.taskListChecked": "Checked List Item", "editor.markup.taskListUnchecked": "Unchecked List Item", + "editor.markup.toggleBold": "Toggle Bold", + "editor.markup.toggleItalic": "Toggle Italic", "editor.markup.togglePreviewPane": "Hide / Show Preview Pane", "editor.markup.toggleSpellcheck": "Toggle Spellcheck", + "editor.markup.saveConfigFailed": "Failed to save markdown editor configuration.", + "editor.markup.saveUserSettingsFailed": "Failed to save markdown editor settings.", "editor.markup.unorderedList": "Unordered List", "editor.page": "Page", "editor.pageData.data": "Data", @@ -1548,8 +1683,13 @@ "editor.pageData.templateStructure": "Structure", "editor.pageData.templateTitle": "Template Title", "editor.pageData.templateUntitled": "Untitled Template", + "editor.pageData.attributeBoolean": "Attribute Boolean", + "editor.pageData.attributeNumber": "Attribute Number", + "editor.pageData.attributeText": "Attribute Text", "editor.pageData.title": "Page Data", + "editor.pageData.visual": "Visual", "editor.pageData.uniqueKey": "Unique Key", + "editor.pageData.yaml": "YAML", "editor.pageRel.button": "Button Appearance", "editor.pageRel.caption": "Caption (optional)", "editor.pageRel.center": "Center", @@ -1671,6 +1811,9 @@ "fileman.epsFileType": "EPS Image", "fileman.exeFileType": "Windows Executable", "fileman.flacFileType": "FLAC Audio File", + "fileman.fetchAssetDataFailed": "Failed to fetch asset data.", + "fileman.fetchFolderDataFailed": "Failed to fetch folder data.", + "fileman.fetchingFolderContents": "Fetching folder contents...", "fileman.folderChildrenCount": "Empty folder | 1 child | {count} children", "fileman.folderCreate": "New Folder", "fileman.folderFileName": "Path Name", @@ -1709,7 +1852,12 @@ "fileman.renameAssetSuccess": "Asset renamed successfully", "fileman.renameFolderInvalidData": "One or more fields are invalid.", "fileman.renameFolderSuccess": "Folder renamed successfully.", + "fileman.browseUsing": "Browse using...", + "fileman.compactList": "Compact List", + "fileman.copyURLFailed": "Failed to copy URL to clipboard.", + "fileman.loadTreeFailed": "Failed to load folder tree.", "fileman.searchFolder": "Search folder...", + "fileman.showFolders": "Show Folders", "fileman.svgFileType": "Scalable Vector Graphic", "fileman.tarFileType": "TAR Archive", "fileman.tgzFileType": "Gzipped TAR Archive", @@ -1718,6 +1866,7 @@ "fileman.ttfFileType": "TrueType Font File", "fileman.txtFileType": "Text Document", "fileman.unknownFileType": "{type} file", + "fileman.uploadFailed": "Failed to upload file.", "fileman.uploadSuccess": "File(s) uploaded successfully.", "fileman.viewOptions": "View Options", "fileman.wavFileType": "WAV Audio File", @@ -1733,10 +1882,25 @@ "folderDeleteDialog.deleteSuccess": "Folder has been deleted successfully.", "folderDeleteDialog.folderId": "Folder ID {id}", "folderDeleteDialog.title": "Confirm Delete Folder", + "headerSearch.operatorExact": "\"foo bar\" matches the exact phrase foo bar.", + "headerSearch.operatorExclude": "!foo or -bar excludes foo and bar.", + "headerSearch.operatorOr": "foo,bar or foo|bar searches for foo OR bar.", + "headerSearch.operatorStartsWith": "bana* matches any term starting with bana, such as banana.", + "headerSearch.operators": "Search Operators", + "headerSearch.placeholder": "Search...", + "headerSearch.popularTags": "Popular Tags", + "headerSearch.pressEnter": "Press Enter", "history.restore.confirmButton": "Restore", "history.restore.confirmText": "Are you sure you want to restore this page content as it was on {date}? This version will be copied on top of the current history. As such, newer versions will still be preserved.", "history.restore.confirmTitle": "Restore page version?", "history.restore.success": "Page version restored succesfully!", + "iconPicker.docsHint": "Learn how to use icons in the {docsLink}.", + "iconPicker.iconTab": "Icon", + "iconPicker.imageTab": "Image", + "iconPicker.iconName": "Icon Name", + "iconPicker.referenceHint": "View the {referenceLink} for all possible options.", + "iconPicker.referenceLink": "Icon Pack reference", + "iconPicker.useIconsLink": "the documentation", "navEdit.clearItems": "Clear All Items", "navEdit.editMenuItems": "Edit Menu Items", "navEdit.emptyMenuText": "Click the Add button to add your first menu item.", @@ -1746,6 +1910,20 @@ "navEdit.label": "Label", "navEdit.labelHint": "Text to display on the menu item.", "navEdit.link": "Link", + "navEdit.mode.hide.hint": "Completely hide the left sidebar navigation.", + "navEdit.mode.hide.label": "Hide", + "navEdit.mode.hideCurrent.hint": "Completely hide the left sidebar navigation only for this path.", + "navEdit.mode.hideCurrent.label": "Hide Current Only", + "navEdit.mode.hideDescendants.hint": "Completely hide the left sidebar navigation for this path and all descendants.", + "navEdit.mode.hideDescendants.label": "Hide Current + Descendants", + "navEdit.mode.inherit.hint": "Use the menu items and settings from the parent path.", + "navEdit.mode.inherit.label": "Inherit", + "navEdit.mode.override.hint": "Set menu items and settings for this path and all descendants.", + "navEdit.mode.override.label": "Override Current + Descendants", + "navEdit.mode.overrideExact.hint": "Set menu items and settings only for this path.", + "navEdit.mode.overrideExact.label": "Override Current Only", + "navEdit.mode.show.hint": "Show the left sidebar navigation menu items.", + "navEdit.mode.show.label": "Show", "navEdit.nestItem": "Nest Item", "navEdit.nestingWarn": "The previous menu item must be a normal link or another nested link. Invalid nested items will be shown in red.", "navEdit.noSelection": "Select a menu item from the left to start editing.", @@ -1767,10 +1945,38 @@ "pageDeleteDialog.deleteSuccess": "Page deleted successfully.", "pageDeleteDialog.pageId": "Page ID {id}", "pageDeleteDialog.title": "Confirm Page Deletion", + "page.notify.createFailed": "Failed to create page.", + "page.notify.createHomeFailed": "Failed to create homepage.", + "page.notify.createHomeSuccess": "Homepage created successfully.", + "page.notify.moveSuccess": "Page moved successfully.", + "page.notify.reloadFailed": "Failed to reload page state.", + "page.notify.renameSuccess": "Page renamed successfully.", + "page.notify.reverted": "Page has been reverted to the last saved state.", + "page.notify.saveFailed": "Failed to save page changes.", + "page.notify.saveSuccess": "Page saved successfully.", + "pageActions.convertPage": "Convert Page", + "pageActions.duplicatePage": "Duplicate Page", + "pageActions.noPendingAssetUploads": "There are no assets pending uploads.", + "pageActions.pendingAssetUploads": "Pending Asset Uploads", + "pageActions.pendingAssetUploadsHint": "Assets pasted or dropped onto this page will be kept here until the page is saved.", + "pageActions.renameMovePage": "Rename / Move Page", + "pageActions.viewBacklinks": "View Backlinks", "pageDuplicateDialog.title": "Duplicate and Save As...", + "pageNewMenu.newApiDocumentation": "New API Documentation", + "pageNewMenu.newAsciiDocPage": "New AsciiDoc Page", + "pageNewMenu.newBlogPage": "New Blog Page", + "pageNewMenu.newDiscussionSpace": "New Discussion Space", + "pageNewMenu.newFolder": "New Folder", + "pageNewMenu.newMarkdownPage": "New Markdown Page", + "pageNewMenu.newPage": "New Page", + "pageNewMenu.newRedirection": "New Redirection", + "pageNewMenu.uploadMediaAsset": "Upload Media Asset", "pageRenameDialog.title": "Rename / Move to...", "pageSaveDialog.displayModePath": "Browse Using Paths", "pageSaveDialog.displayModeTitle": "Browse Using Titles", + "pageSaveDialog.displayOptions": "Display Options", + "pageSaveDialog.loadTreeFailed": "Failed to load folder tree.", + "pageSaveDialog.pathName": "Path Name", "pageSaveDialog.title": "Save As...", "profile.accessibility": "Accessibility", "profile.activity": "Activity", @@ -1866,6 +2072,7 @@ "renderPageDialog.success": "Page rerendered successfully.", "search.editorAny": "Any editor", "search.emptyQuery": "Enter a query in the search field above and press Enter.", + "search.failedQuery": "Failed to perform search query.", "search.filterEditor": "Editor", "search.filterLocale": "Locale(s)", "search.filterLocaleDisplay": "Any locale | {n} locale only | {count} locales selected", @@ -1907,5 +2114,8 @@ "welcome.homeDefault.description": "Welcome to my wiki!", "welcome.homeDefault.title": "Home", "welcome.subtitle": "Let's get started...", - "welcome.title": "Welcome to Wiki.js!" + "welcome.title": "Welcome to Wiki.js!", + "welcome.usingAsciiDocEditor": "Using the AsciiDoc Editor", + "welcome.usingMarkdownEditor": "Using the Markdown Editor", + "welcome.usingVisualEditor": "Using the Visual Editor" } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 504d0a7790..7520a85562 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -65,7 +65,7 @@ async function applyLocale (locale) { } catch (err) { $q.notify({ type: 'negative', - message: `Failed to load ${locale} locale strings.`, + message: i18n.t('common.locale.loadFailed', { locale }), caption: err.message }) } diff --git a/frontend/src/components/ApiKeyCreateDialog.vue b/frontend/src/components/ApiKeyCreateDialog.vue index ccc331bcae..8d108565bf 100644 --- a/frontend/src/components/ApiKeyCreateDialog.vue +++ b/frontend/src/components/ApiKeyCreateDialog.vue @@ -236,7 +236,7 @@ async function create () { onDialogOK() }) } else { - throw new Error(resp?.data?.createApiKey?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.createApiKey?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/ApiKeyRevokeDialog.vue b/frontend/src/components/ApiKeyRevokeDialog.vue index 77e6144d80..11c640dc72 100644 --- a/frontend/src/components/ApiKeyRevokeDialog.vue +++ b/frontend/src/components/ApiKeyRevokeDialog.vue @@ -91,7 +91,7 @@ async function confirm () { }) onDialogOK() } else { - throw new Error(resp?.data?.revokeApiKey?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.revokeApiKey?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/AssetDeleteDialog.vue b/frontend/src/components/AssetDeleteDialog.vue index 974cddb5b4..dd88ea961b 100644 --- a/frontend/src/components/AssetDeleteDialog.vue +++ b/frontend/src/components/AssetDeleteDialog.vue @@ -96,7 +96,7 @@ async function confirm () { }) onDialogOK() } else { - throw new Error(resp?.data?.deleteAsset?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.deleteAsset?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/AssetRenameDialog.vue b/frontend/src/components/AssetRenameDialog.vue index 95b71603dc..4675aee619 100644 --- a/frontend/src/components/AssetRenameDialog.vue +++ b/frontend/src/components/AssetRenameDialog.vue @@ -115,7 +115,7 @@ async function rename () { }) onDialogOK() } else { - throw new Error(resp?.data?.renameAsset?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.renameAsset?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ @@ -150,7 +150,7 @@ onMounted(async () => { } }) if (resp?.data?.assetById?.id !== props.assetId) { - throw new Error('Failed to fetch asset data.') + throw new Error(t('fileman.fetchAssetDataFailed')) } state.path = resp.data.assetById.fileName } catch (err) { diff --git a/frontend/src/components/AuthLoginPanel.vue b/frontend/src/components/AuthLoginPanel.vue index 773103eb85..6414600c5a 100644 --- a/frontend/src/components/AuthLoginPanel.vue +++ b/frontend/src/components/AuthLoginPanel.vue @@ -510,7 +510,7 @@ function switchTo (screen) { break } default: { - throw new Error('Invalid Screen') + throw new Error(t('common.error.unexpected')) } } } @@ -576,7 +576,7 @@ async function handleLoginResponse (resp) { $q.loading.hide() $q.notify({ type: 'negative', - message: 'Unexpected Authentication Response' + message: t('auth.errors.unexpectedResponse') }) } } @@ -705,7 +705,7 @@ async function forgotPassword () { // TODO: Implement forgot password $q.notify({ type: 'negative', - message: 'Not implemented yet.' + message: t('auth.forgotPasswordUnavailable') }) } catch (err) { $q.notify({ diff --git a/frontend/src/components/ChangePwdDialog.vue b/frontend/src/components/ChangePwdDialog.vue index 784f8b0a34..f0e8893df8 100644 --- a/frontend/src/components/ChangePwdDialog.vue +++ b/frontend/src/components/ChangePwdDialog.vue @@ -48,7 +48,7 @@ q-dialog(ref='dialogRef', @hide='onDialogHide') @click='randomizePassword' ) q-icon(name='las la-dice-d6') - .q-pl-xs.text-caption: strong Generate + .q-pl-xs.text-caption: strong {{ t('common.actions.generate') }} q-item blueprint-icon(icon='good-pincode') q-item-section @@ -235,7 +235,7 @@ async function save () { }) onDialogOK() } else { - throw new Error(resp?.data?.changePassword?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.changePassword?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/CheckUpdateDialog.vue b/frontend/src/components/CheckUpdateDialog.vue index 085c2de56b..e7a31e6881 100644 --- a/frontend/src/components/CheckUpdateDialog.vue +++ b/frontend/src/components/CheckUpdateDialog.vue @@ -94,7 +94,7 @@ async function check () { state.latest = resp.latest state.latestDate = DateTime.fromISO(resp.latestDate).toFormat(userStore.preferredDateFormat) } else { - throw new Error(resp?.message || 'An unexpected error occured.') + throw new Error(resp?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/EditorMarkdown.vue b/frontend/src/components/EditorMarkdown.vue index cbb7e6b87a..dd2ccd3379 100644 --- a/frontend/src/components/EditorMarkdown.vue +++ b/frontend/src/components/EditorMarkdown.vue @@ -26,7 +26,7 @@ q-item-section(side) q-icon(name='las la-folder-open', color='positive') q-item-section - q-item-label From File Manager... + q-item-label {{ t('editor.markup.fromFileManager') }} q-item( clickable @click='getAssetFromClipboard' @@ -35,7 +35,7 @@ q-item-section(side) q-icon(name='las la-clipboard', color='brown') q-item-section - q-item-label From Clipboard... + q-item-label {{ t('editor.markup.fromClipboard') }} q-item( clickable @click='notImplemented' @@ -44,7 +44,7 @@ q-item-section(side) q-icon(name='las la-cloud-download-alt', color='blue') q-item-section - q-item-label From Remote URL... + q-item-label {{ t('editor.markup.fromRemoteURL') }} q-tooltip(anchor='center right' self='center left') {{ t('editor.markup.insertAssets') }} q-btn( icon='mdi-code-json' @@ -103,7 +103,7 @@ ) q-tooltip(anchor='center right' self='center left') {{ t('editor.markup.insertHorizontalBar') }} q-space - span.editor-markdown-type Markdown + span.editor-markdown-type {{ t('editor.markup.markdown') }} .editor-markdown-mid //-------------------------------------------------------- //- TOP TOOLBAR @@ -506,7 +506,7 @@ async function getAssetFromClipboard () { name: 'clipboard-read' }) if (permission.state === 'denied') { - throw new Error('Not allowed to read clipboard.') + throw new Error(t('editor.markup.clipboardReadDenied')) } const clipboardContents = await navigator.clipboard.read() let hasValidItem = false @@ -522,12 +522,12 @@ async function getAssetFromClipboard () { } } if (!hasValidItem) { - throw new Error('No supported content found in the Clipboard.') + throw new Error(t('editor.markup.clipboardUnsupported')) } } catch (err) { return $q.notify({ type: 'negative', - message: 'Unable to copy from Clipboard', + message: t('editor.markup.clipboardError'), caption: err.message }) } @@ -592,7 +592,7 @@ onMounted(async () => { contextMenuOrder: 0, id: 'markdown.extension.editing.toggleBold', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB], - label: 'Toggle bold', + label: t('editor.markup.toggleBold'), precondition: '', run (ed) { toggleMarkup({ start: '**' }) @@ -604,7 +604,7 @@ onMounted(async () => { contextMenuOrder: 0, id: 'markdown.extension.editing.toggleItalic', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI], - label: 'Toggle italic', + label: t('editor.markup.toggleItalic'), precondition: '', run (ed) { toggleMarkup({ start: '*' }) @@ -614,7 +614,7 @@ onMounted(async () => { editor.addAction({ id: 'markdown.extension.editing.increaseHeaderLevel', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.RightArrow], - label: 'Increase Header Level', + label: t('editor.markup.increaseHeaderLevel'), precondition: '', run (ed) { let lvl = getHeaderLevel() @@ -625,7 +625,7 @@ onMounted(async () => { editor.addAction({ id: 'markdown.extension.editing.decreaseHeaderLevel', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.LeftArrow], - label: 'Decrease Header Level', + label: t('editor.markup.decreaseHeaderLevel'), precondition: '', run (ed) { let lvl = getHeaderLevel() @@ -637,7 +637,7 @@ onMounted(async () => { editor.addAction({ id: 'save', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS], - label: 'Save', + label: t('common.actions.save'), precondition: '', run (ed) { } @@ -754,7 +754,7 @@ onBeforeUnmount(() => { function notImplemented () { $q.notify({ type: 'negative', - message: 'Not implemented' + message: t('common.error.notImplemented') }) } diff --git a/frontend/src/components/EditorMarkdownConfigOverlay.vue b/frontend/src/components/EditorMarkdownConfigOverlay.vue index 320d6ede03..4a970d0212 100644 --- a/frontend/src/components/EditorMarkdownConfigOverlay.vue +++ b/frontend/src/components/EditorMarkdownConfigOverlay.vue @@ -353,7 +353,7 @@ async function load () { } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to fetch markdown editor configuration.' + message: t('editor.markup.fetchConfigFailed') }) } $q.loading.hide() @@ -398,12 +398,12 @@ async function save () { editorStore.$patch({ configIsLoaded: false }) close() } else { - throw new Error(respRaw?.data?.updateSite?.operation?.message || 'An unexpected error occured.') + throw new Error(respRaw?.data?.updateSite?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to save Markdown editor config', + message: t('editor.markup.saveConfigFailed'), caption: err.message }) } diff --git a/frontend/src/components/EditorMarkdownUserSettingsOverlay.vue b/frontend/src/components/EditorMarkdownUserSettingsOverlay.vue index 67215948ae..7a93ca108a 100644 --- a/frontend/src/components/EditorMarkdownUserSettingsOverlay.vue +++ b/frontend/src/components/EditorMarkdownUserSettingsOverlay.vue @@ -141,7 +141,7 @@ async function load () { } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to fetch Markdown editor settings.' + message: t('editor.markup.fetchUserSettingsFailed') }) } $q.loading.hide() @@ -179,12 +179,12 @@ async function save () { }) close() } else { - throw new Error(respRaw?.data?.saveUserEditorSettings?.operation?.message || 'An unexpected error occured.') + throw new Error(respRaw?.data?.saveUserEditorSettings?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to save Markdown editor settings.', + message: t('editor.markup.saveUserSettingsFailed'), caption: err.message }) } diff --git a/frontend/src/components/FileManager.vue b/frontend/src/components/FileManager.vue index eaa2c11a15..e873a71b39 100644 --- a/frontend/src/components/FileManager.vue +++ b/frontend/src/components/FileManager.vue @@ -134,7 +134,7 @@ q-layout.fileman(view='hHh lpR lFr', container) q-item(clickable) q-item-section(side) q-icon(name='las la-list', color='grey', size='xs') - q-item-section.q-pr-sm Browse using... + q-item-section.q-pr-sm {{ t('fileman.browseUsing') }} q-item-section(side) q-icon(name='las la-angle-right', color='grey', size='xs') q-menu( @@ -149,7 +149,7 @@ q-layout.fileman(view='hHh lpR lFr', container) :color='state.displayMode === `path` ? `positive` : `grey`' size='xs' ) - q-item-section.q-pr-sm Browse Using Paths + q-item-section.q-pr-sm {{ t('pageSaveDialog.displayModePath') }} q-item(clickable, @click='state.displayMode = `title`') q-item-section(side) q-icon( @@ -157,7 +157,7 @@ q-layout.fileman(view='hHh lpR lFr', container) :color='state.displayMode === `title` ? `positive` : `grey`' size='xs' ) - q-item-section.q-pr-sm Browse Using Titles + q-item-section.q-pr-sm {{ t('pageSaveDialog.displayModeTitle') }} q-item(clickable, @click='state.isCompact = !state.isCompact') q-item-section(side) q-icon( @@ -165,7 +165,7 @@ q-layout.fileman(view='hHh lpR lFr', container) :color='state.isCompact ? `positive` : `grey`' size='xs' ) - q-item-section.q-pr-sm Compact List + q-item-section.q-pr-sm {{ t('fileman.compactList') }} q-item(clickable, @click='state.shouldShowFolders = !state.shouldShowFolders') q-item-section(side) q-icon( @@ -173,7 +173,7 @@ q-layout.fileman(view='hHh lpR lFr', container) :color='state.shouldShowFolders ? `positive` : `grey`' size='xs' ) - q-item-section.q-pr-sm Show Folders + q-item-section.q-pr-sm {{ t('fileman.showFolders') }} q-btn.q-mr-sm( flat dense @@ -221,10 +221,10 @@ q-layout.fileman(view='hHh lpR lFr', container) ) .fileman-loadinglist(v-if='state.fileListLoading') q-spinner.q-mr-sm(color='primary', size='64px', :thickness='1') - span.text-primary Fetching folder contents... + span.text-primary {{ t('fileman.fetchingFolderContents') }} .fileman-emptylist(v-else-if='files.length < 1') img(src='/_assets/icons/carbon-copy-empty-box.svg') - span This folder is empty. + span {{ t('common.pageSelector.folderEmptyWarning') }} q-list.fileman-filelist( v-else :class='state.isCompact && `is-compact`' @@ -689,7 +689,7 @@ async function loadTree ({ parentId = null, parentPath = null, types, initLoad = } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to load folder tree.', + message: t('fileman.loadTreeFailed'), caption: err.message }) } @@ -900,7 +900,7 @@ async function uploadNewFiles () { } }) if (!resp?.data?.uploadAssets?.operation?.succeeded) { - throw new Error(resp?.data?.uploadAssets?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.uploadAssets?.operation?.message || t('common.error.unexpected')) } } state.uploadPercentage = 100 @@ -912,7 +912,7 @@ async function uploadNewFiles () { } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to upload file.', + message: t('fileman.uploadFailed'), caption: err.message }) } @@ -995,7 +995,7 @@ async function copyItemURL (item) { } catch (err) { $q.notify({ type: 'negative', - message: 'Failed to copy URL to clipboard.', + message: t('fileman.copyURLFailed'), caption: err.message }) } diff --git a/frontend/src/components/FolderCreateDialog.vue b/frontend/src/components/FolderCreateDialog.vue index 332af16160..fb63ffdc31 100644 --- a/frontend/src/components/FolderCreateDialog.vue +++ b/frontend/src/components/FolderCreateDialog.vue @@ -177,7 +177,7 @@ async function create () { }) onDialogOK() } else { - throw new Error(resp?.data?.createFolder?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.createFolder?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/FolderDeleteDialog.vue b/frontend/src/components/FolderDeleteDialog.vue index 9428289267..d3f8a5a429 100644 --- a/frontend/src/components/FolderDeleteDialog.vue +++ b/frontend/src/components/FolderDeleteDialog.vue @@ -96,7 +96,7 @@ async function confirm () { }) onDialogOK() } else { - throw new Error(resp?.data?.deleteFolder?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.deleteFolder?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/FolderRenameDialog.vue b/frontend/src/components/FolderRenameDialog.vue index e07d9c1147..8c51c6d5e0 100644 --- a/frontend/src/components/FolderRenameDialog.vue +++ b/frontend/src/components/FolderRenameDialog.vue @@ -173,7 +173,7 @@ async function rename () { }) onDialogOK() } else { - throw new Error(resp?.data?.renameFolder?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.renameFolder?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ @@ -210,7 +210,7 @@ onMounted(async () => { } }) if (resp?.data?.folderById?.id !== props.folderId) { - throw new Error('Failed to fetch folder data.') + throw new Error(t('fileman.fetchFolderDataFailed')) } state.path = resp.data.folderById.fileName state.title = resp.data.folderById.title diff --git a/frontend/src/components/GroupCreateDialog.vue b/frontend/src/components/GroupCreateDialog.vue index 6d9f52429e..6a83a7adc4 100644 --- a/frontend/src/components/GroupCreateDialog.vue +++ b/frontend/src/components/GroupCreateDialog.vue @@ -112,7 +112,7 @@ async function create () { }) onDialogOK() } else { - throw new Error(resp?.data?.createGroup?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.createGroup?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/GroupDeleteDialog.vue b/frontend/src/components/GroupDeleteDialog.vue index c13e73e005..03b5ff0fc6 100644 --- a/frontend/src/components/GroupDeleteDialog.vue +++ b/frontend/src/components/GroupDeleteDialog.vue @@ -84,7 +84,7 @@ async function confirm () { }) onDialogOK() } else { - throw new Error(resp?.data?.deleteGroup?.operation?.message || 'An unexpected error occured.') + throw new Error(resp?.data?.deleteGroup?.operation?.message || t('common.error.unexpected')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/GroupEditOverlay.vue b/frontend/src/components/GroupEditOverlay.vue index 9b004d0ce1..49f66b02d9 100644 --- a/frontend/src/components/GroupEditOverlay.vue +++ b/frontend/src/components/GroupEditOverlay.vue @@ -174,7 +174,7 @@ q-layout(view='hHh lpR fFf', container) unelevated color='primary' icon='las la-plus' - label='New Rule' + :label='t(`admin.groups.newRule`)' @click='newRule' ) q-separator @@ -597,49 +597,49 @@ const usersHeaders = [ const permissions = [ { permission: 'access:admin', - hint: 'Can access the administration area.', + hint: t('admin.groups.permissions.accessAdminHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:users', - hint: 'Can create / manage users (but not users with administrative permissions)', + hint: t('admin.groups.permissions.manageUsersHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:groups', - hint: 'Can create / manage groups and assign permissions (but not manage:system) / page rules', + hint: t('admin.groups.permissions.manageGroupsHint'), warning: true, restrictedForSystem: true, disabled: false }, { permission: 'manage:navigation', - hint: 'Can manage site navigation', + hint: t('admin.groups.permissions.manageNavigationHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:theme', - hint: 'Can modify site theme settings', + hint: t('admin.groups.permissions.manageThemeHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:sites', - hint: 'Can create / manage sites', + hint: t('admin.groups.permissions.manageSitesHint'), warning: true, restrictedForSystem: true, disabled: false }, { permission: 'manage:system', - hint: 'Can manage and access everything. Root administrator.', + hint: t('admin.groups.permissions.manageSystemHint'), warning: true, restrictedForSystem: true, disabled: true @@ -649,120 +649,120 @@ const permissions = [ const rules = [ { permission: 'read:pages', - title: 'Read Pages', - hint: 'Can view and search pages.', + title: t('admin.groups.permissions.readPagesTitle'), + hint: t('admin.groups.permissions.readPagesHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'write:pages', - title: 'Write Pages', - hint: 'Can create and edit pages.', + title: t('admin.groups.permissions.writePagesTitle'), + hint: t('admin.groups.permissions.writePagesHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'review:pages', - title: 'Review Pages', - hint: 'Can review and approve edits submitted by users.', + title: t('admin.groups.permissions.reviewPagesTitle'), + hint: t('admin.groups.permissions.reviewPagesHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:pages', - title: 'Manage Pages', - hint: 'Can move existing pages to other locations the user has write access to.', + title: t('admin.groups.permissions.managePagesTitle'), + hint: t('admin.groups.permissions.managePagesHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'delete:pages', - title: 'Delete Pages', - hint: 'Can delete existing pages.', + title: t('admin.groups.permissions.deletePagesTitle'), + hint: t('admin.groups.permissions.deletePagesHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'write:styles', - title: 'Use CSS', - hint: 'Can insert CSS styles in pages.', + title: t('admin.groups.permissions.useCssTitle'), + hint: t('admin.groups.permissions.useCssHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'write:scripts', - title: 'Use JavaScript', - hint: 'Can insert JavaScript in pages.', + title: t('admin.groups.permissions.useJavaScriptTitle'), + hint: t('admin.groups.permissions.useJavaScriptHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'read:source', - title: 'View Page Source', - hint: 'Can view pages source.', + title: t('admin.groups.permissions.viewPageSourceTitle'), + hint: t('admin.groups.permissions.viewPageSourceHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'read:history', - title: 'View Page History', - hint: 'Can view previous versions of pages.', + title: t('admin.groups.permissions.viewPageHistoryTitle'), + hint: t('admin.groups.permissions.viewPageHistoryHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'read:assets', - title: 'View Assets', - hint: 'Can view / use assets (such as images and files) in pages.', + title: t('admin.groups.permissions.viewAssetsTitle'), + hint: t('admin.groups.permissions.viewAssetsHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'write:assets', - title: 'Upload Assets', - hint: 'Can upload new assets (such as images and files).', + title: t('admin.groups.permissions.uploadAssetsTitle'), + hint: t('admin.groups.permissions.uploadAssetsHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'manage:assets', - title: 'Manage Assets', - hint: 'Can edit and delete existing assets (such as images and files).', + title: t('admin.groups.permissions.manageAssetsTitle'), + hint: t('admin.groups.permissions.manageAssetsHint'), warning: false, restrictedForSystem: true, disabled: false }, { permission: 'read:comments', - title: 'Read Comments', - hint: 'Can view page comments.', + title: t('admin.groups.permissions.readCommentsTitle'), + hint: t('admin.groups.permissions.readCommentsHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'write:comments', - title: 'Write Comments', - hint: 'Can post new comments on pages.', + title: t('admin.groups.permissions.writeCommentsTitle'), + hint: t('admin.groups.permissions.writeCommentsHint'), warning: false, restrictedForSystem: false, disabled: false }, { permission: 'manage:comments', - title: 'Manage Comments', - hint: 'Can edit and delete existing page comments.', + title: t('admin.groups.permissions.manageCommentsTitle'), + hint: t('admin.groups.permissions.manageCommentsHint'), warning: false, restrictedForSystem: true, disabled: false @@ -902,7 +902,7 @@ async function fetchGroup () { state.group = cloneDeep(resp.data.groupById) state.usersTotal = state.group.userCount ?? 0 } else { - throw new Error('An unexpected error occured while fetching group details.') + throw new Error(t('admin.groups.fetchDetailsFailed')) } } catch (err) { $q.notify({ @@ -952,7 +952,7 @@ async function importRules () { const rulesRaw = await blob.text() const rules = JSON.parse(rulesRaw) if (!Array.isArray(rules) || rules.length < 1) { - throw new Error('Invalid Rules Format') + throw new Error(t('admin.groups.invalidRulesFormat')) } $q.dialog({ title: t('admin.groups.importModeTitle'), @@ -1040,7 +1040,7 @@ async function refreshUsers () { state.usersTotal = resp.data.groupById.userCount ?? 0 state.users = cloneDeep(resp.data.groupById.users) } else { - throw new Error('An unexpected error occured while fetching group users.') + throw new Error(t('admin.groups.fetchUsersFailed')) } } catch (err) { $q.notify({ diff --git a/frontend/src/components/HeaderNav.vue b/frontend/src/components/HeaderNav.vue index 22e9951fe2..819f2b3d7a 100644 --- a/frontend/src/components/HeaderNav.vue +++ b/frontend/src/components/HeaderNav.vue @@ -43,9 +43,9 @@ q-header.bg-header.text-white.site-header( dense icon='las la-plus-circle' color='blue-4' - aria-label='Create New Page' + :aria-label='t(`common.header.newPage`)' ) - q-tooltip Create New Page + q-tooltip {{ t('common.header.newPage') }} new-menu q-btn.q-ml-md( v-if='userStore.can(`browse:fileman`)' @@ -54,10 +54,10 @@ q-header.bg-header.text-white.site-header( dense icon='las la-folder-open' color='positive' - aria-label='File Manager' + :aria-label='t(`fileman.title`)' @click='openFileManager' ) - q-tooltip File Manager + q-tooltip {{ t('fileman.title') }} q-btn.q-ml-md( v-if='userStore.can(`access:admin`)' flat diff --git a/frontend/src/components/HeaderSearch.vue b/frontend/src/components/HeaderSearch.vue index f45073fb32..e515eda94e 100644 --- a/frontend/src/components/HeaderSearch.vue +++ b/frontend/src/components/HeaderSearch.vue @@ -12,7 +12,7 @@ q-toolbar( rounded ref='searchField' style='width: 100%;' - label='Search...' + :label='t(`headerSearch.placeholder`)' @keyup.enter='onSearchEnter' @focus='state.searchIsFocused = true' @blur='checkSearchFocus' @@ -37,7 +37,7 @@ q-toolbar( ) q-badge.q-mr-sm( v-else-if='siteStore.search && siteStore.search !== siteStore.searchLastQuery' - label='Press Enter' + :label='t(`headerSearch.pressEnter`)' color='grey-7' outline @click='searchField.focus()' @@ -55,11 +55,11 @@ q-toolbar( ) template(v-if='siteStore.tagsLoaded && siteStore.tags.length > 0') .searchpanel-header - span Popular Tags + span {{ t('headerSearch.popularTags') }} q-space q-btn.acrylic-btn( flat - label='View All' + :label='t(`common.actions.viewAll`)' rounded size='xs' ) @@ -75,11 +75,11 @@ q-toolbar( clickable @click='addTag(tag)' ) {{ tag }} - .searchpanel-header Search Operators - .searchpanel-tip #[code !foo] or #[code -bar] to exclude "foo" and "bar". - .searchpanel-tip #[code bana*] for to match any term starting with "bana" (e.g. banana). - .searchpanel-tip #[code foo,bar] or #[code foo|bar] to search for "foo" OR "bar". - .searchpanel-tip #[code "foo bar"] to match exactly the phrase "foo bar". + .searchpanel-header {{ t('headerSearch.operators') }} + .searchpanel-tip {{ t('headerSearch.operatorExclude') }} + .searchpanel-tip {{ t('headerSearch.operatorStartsWith') }} + .searchpanel-tip {{ t('headerSearch.operatorOr') }} + .searchpanel-tip {{ t('headerSearch.operatorExact') }} diff --git a/frontend/src/components/PageDataDialog.vue b/frontend/src/components/PageDataDialog.vue index e644cb7055..fd9249c94f 100644 --- a/frontend/src/components/PageDataDialog.vue +++ b/frontend/src/components/PageDataDialog.vue @@ -41,11 +41,11 @@ q-card.page-data-dialog(style='width: 750px;') ) q-tab( name='visual' - label='Visual' + :label='t(`editor.pageData.visual`)' ) q-tab( name='code' - label='YAML' + :label='t(`editor.pageData.yaml`)' ) q-scroll-area( :thumb-style='siteStore.thumbStyle' @@ -55,14 +55,14 @@ q-card.page-data-dialog(style='width: 750px;') q-card-section(v-if='state.mode === `visual`') .q-gutter-sm q-input( - label='Attribute Text' + :label='t(`editor.pageData.attributeText`)' dense outlined ) template(v-slot:before) q-icon(name='las la-font', color='primary') q-input( - label='Attribute Number' + :label='t(`editor.pageData.attributeNumber`)' dense outlined type='number' @@ -71,7 +71,7 @@ q-card.page-data-dialog(style='width: 750px;') q-icon(name='las la-infinity', color='primary') .q-py-xs q-checkbox( - label='Attribute Boolean' + :label='t(`editor.pageData.attributeBoolean`)' color='primary' dense size='lg' @@ -92,7 +92,7 @@ q-card.page-data-dialog(style='width: 750px;') diff --git a/frontend/src/components/PageNewMenu.vue b/frontend/src/components/PageNewMenu.vue index 969d80c40c..04046645a3 100644 --- a/frontend/src/components/PageNewMenu.vue +++ b/frontend/src/components/PageNewMenu.vue @@ -11,14 +11,14 @@ q-menu.translucent-menu( v-if='siteStore.editors.wysiwyg && flagsStore.experimental' ) blueprint-icon(icon='google-presentation') - q-item-section.q-pr-sm New Page + q-item-section.q-pr-sm {{ t('pageNewMenu.newPage') }} q-item( clickable @click='create(`markdown`)' v-if='siteStore.editors.markdown' ) blueprint-icon(icon='markdown') - q-item-section.q-pr-sm New Markdown Page + q-item-section.q-pr-sm {{ t('pageNewMenu.newMarkdownPage') }} template(v-if='flagsStore.experimental') q-item( clickable @@ -26,31 +26,31 @@ q-menu.translucent-menu( v-if='siteStore.editors.asciidoc' ) blueprint-icon(icon='asciidoc') - q-item-section.q-pr-sm New AsciiDoc Page + q-item-section.q-pr-sm {{ t('pageNewMenu.newAsciiDocPage') }} q-item( clickable @click='create(`channel`)' ) blueprint-icon(icon='chat') - q-item-section.q-pr-sm New Discussion Space + q-item-section.q-pr-sm {{ t('pageNewMenu.newDiscussionSpace') }} q-item( clickable @click='create(`blog`)' ) blueprint-icon(icon='typewriter-with-paper') - q-item-section.q-pr-sm New Blog Page + q-item-section.q-pr-sm {{ t('pageNewMenu.newBlogPage') }} q-item( clickable @click='create(`api`)' ) blueprint-icon(icon='api') - q-item-section.q-pr-sm New API Documentation + q-item-section.q-pr-sm {{ t('pageNewMenu.newApiDocumentation') }} q-item( clickable @click='create(`redirect`)' ) blueprint-icon(icon='advance') - q-item-section.q-pr-sm New Redirection + q-item-section.q-pr-sm {{ t('pageNewMenu.newRedirection') }} template(v-if='props.hideAssetBtn === false') q-separator.q-my-sm(inset) q-item( @@ -58,7 +58,7 @@ q-menu.translucent-menu( @click='openFileManager' ) blueprint-icon(icon='add-image') - q-item-section.q-pr-sm Upload Media Asset + q-item-section.q-pr-sm {{ t('pageNewMenu.uploadMediaAsset') }} template(v-if='props.showNewFolder') q-separator.q-my-sm(inset) q-item( @@ -66,7 +66,7 @@ q-menu.translucent-menu( @click='newFolder' ) blueprint-icon(icon='add-folder') - q-item-section.q-pr-sm New Folder + q-item-section.q-pr-sm {{ t('pageNewMenu.newFolder') }}