From df6bcff8b3cfe4865241e73e4bf85497da94762d Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Tue, 29 Jul 2025 15:48:13 +0200 Subject: [PATCH] Update browser extension and app translations --- .../entrypoints/popup/pages/AuthSettings.tsx | 4 +- .../entrypoints/popup/pages/EmailsList.tsx | 8 +-- .../src/entrypoints/popup/pages/Upgrade.tsx | 58 ++++++++--------- .../src/i18n/locales/en.json | 33 ++++++++++ apps/mobile-app/app/(tabs)/emails/_layout.tsx | 6 +- apps/mobile-app/app/_layout.tsx | 26 ++++---- apps/mobile-app/app/reinitialize.tsx | 24 +++---- apps/mobile-app/app/unlock.tsx | 2 +- apps/mobile-app/app/upgrade.tsx | 64 ++++++++++--------- apps/mobile-app/i18n/locales/en.json | 57 ++++++++++++++++- 10 files changed, 188 insertions(+), 94 deletions(-) diff --git a/apps/browser-extension/src/entrypoints/popup/pages/AuthSettings.tsx b/apps/browser-extension/src/entrypoints/popup/pages/AuthSettings.tsx index aaf683bbd..c57d715db 100644 --- a/apps/browser-extension/src/entrypoints/popup/pages/AuthSettings.tsx +++ b/apps/browser-extension/src/entrypoints/popup/pages/AuthSettings.tsx @@ -27,7 +27,7 @@ const DEFAULT_OPTIONS: ApiOption[] = [ const createUrlSchema = (t: (key: string) => string): Yup.ObjectSchema<{apiUrl: string; clientUrl: string}> => Yup.object().shape({ apiUrl: Yup.string() .required(t('validation.apiUrlRequired')) - .test('is-valid-api-url', t('validation.apiUrlInvalid'), (value: string | undefined) => { + .test('is-valid-api-url', t('settings.validation.apiUrlInvalid'), (value: string | undefined) => { if (!value) { return true; // Allow empty for non-custom option } @@ -40,7 +40,7 @@ const createUrlSchema = (t: (key: string) => string): Yup.ObjectSchema<{apiUrl: }), clientUrl: Yup.string() .required(t('validation.clientUrlRequired')) - .test('is-valid-client-url', t('validation.clientUrlInvalid'), (value: string | undefined) => { + .test('is-valid-client-url', t('settings.validation.clientUrlInvalid'), (value: string | undefined) => { if (!value) { return true; // Allow empty for non-custom option } diff --git a/apps/browser-extension/src/entrypoints/popup/pages/EmailsList.tsx b/apps/browser-extension/src/entrypoints/popup/pages/EmailsList.tsx index c05f986c4..4cc2dd38e 100644 --- a/apps/browser-extension/src/entrypoints/popup/pages/EmailsList.tsx +++ b/apps/browser-extension/src/entrypoints/popup/pages/EmailsList.tsx @@ -111,17 +111,17 @@ const EmailsList: React.FC = () => { // Less than 1 hour ago const minutes = Math.floor(secondsAgo / 60); if (minutes === 1) { - return t('emails.time.minutesAgo_single', { count: minutes }); + return t('emails.dateFormat.minutesAgo_single', { count: minutes }); } else { - return t('emails.time.minutesAgo_plural', { count: minutes }); + return t('emails.dateFormat.minutesAgo_plural', { count: minutes }); } } else if (secondsAgo < 86400) { // Less than 24 hours ago const hours = Math.floor(secondsAgo / 3600); if (hours === 1) { - return t('emails.time.hoursAgo_single', { count: hours }); + return t('emails.dateFormat.hoursAgo_single', { count: hours }); } else { - return t('emails.time.hoursAgo_plural', { count: hours }); + return t('emails.dateFormat.hoursAgo_plural', { count: hours }); } } else if (secondsAgo < 172800) { // Less than 48 hours ago diff --git a/apps/browser-extension/src/entrypoints/popup/pages/Upgrade.tsx b/apps/browser-extension/src/entrypoints/popup/pages/Upgrade.tsx index d468d8e89..c12003369 100644 --- a/apps/browser-extension/src/entrypoints/popup/pages/Upgrade.tsx +++ b/apps/browser-extension/src/entrypoints/popup/pages/Upgrade.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import Button from '@/entrypoints/popup/components/Button'; @@ -22,6 +23,7 @@ import { VaultSqlGenerator } from '@/utils/dist/shared/vault-sql'; * Upgrade page for handling vault version upgrades. */ const Upgrade: React.FC = () => { + const { t } = useTranslation(); const { username } = useAuth(); const dbContext = useDb(); const { sqliteClient } = dbContext; @@ -44,7 +46,7 @@ const Upgrade: React.FC = () => { <> PopoutUtility.openInNewPopup()} - title="Open in new window" + title={t('common.openInNewWindow')} iconType={HeaderIconType.EXPAND} /> @@ -55,7 +57,7 @@ const Upgrade: React.FC = () => { return () => { setHeaderButtons(null); }; - }, [setHeaderButtons]); + }, [setHeaderButtons, t]); /** * Load version information from the database. @@ -71,9 +73,9 @@ const Upgrade: React.FC = () => { setIsInitialLoading(false); } catch (error) { console.error('Failed to load version information:', error); - setError('Failed to load version information. Please try again.'); + setError(t('upgrade.alerts.unableToGetVersionInfo')); } - }, [sqliteClient, setIsInitialLoading]); + }, [sqliteClient, setIsInitialLoading, t]); useEffect(() => { loadVersionInfo(); @@ -84,7 +86,7 @@ const Upgrade: React.FC = () => { */ const handleUpgrade = async (): Promise => { if (!sqliteClient || !currentVersion || !latestVersion) { - setError('Unable to get version information. Please try again.'); + setError(t('upgrade.alerts.unableToGetVersionInfo')); return; } @@ -102,7 +104,7 @@ const Upgrade: React.FC = () => { */ const performUpgrade = async (): Promise => { if (!sqliteClient || !currentVersion || !latestVersion) { - setError('Unable to get version information. Please try again.'); + setError(t('upgrade.alerts.unableToGetVersionInfo')); return; } @@ -115,7 +117,7 @@ const Upgrade: React.FC = () => { const upgradeResult = vaultSqlGenerator.getUpgradeVaultSql(currentVersion.revision, latestVersion.revision); if (!upgradeResult.success) { - throw new Error(upgradeResult.error ?? 'Failed to generate upgrade SQL'); + throw new Error(upgradeResult.error ?? t('upgrade.alerts.upgradeFailed')); } if (upgradeResult.sqlCommands.length === 0) { @@ -125,30 +127,24 @@ const Upgrade: React.FC = () => { } // Use the useVaultMutate hook to handle the upgrade and vault upload - console.debug('executeVaultMutation'); await executeVaultMutation(async () => { // Begin transaction - console.debug('beginTransaction'); sqliteClient.beginTransaction(); // Execute each SQL command - console.debug('executeRaw', upgradeResult.sqlCommands.length); for (let i = 0; i < upgradeResult.sqlCommands.length; i++) { const sqlCommand = upgradeResult.sqlCommands[i]; try { - console.debug('executeRaw', sqlCommand); sqliteClient.executeRaw(sqlCommand); } catch (error) { - console.debug('error', error); console.error(`Error executing SQL command ${i + 1}:`, sqlCommand, error); sqliteClient.rollbackTransaction(); - throw new Error(`Failed to apply migration ${i + 1}: ${error instanceof Error ? error.message : 'Unknown error'}`); + throw new Error(t('upgrade.alerts.failedToApplyMigration', { current: i + 1, total: upgradeResult.sqlCommands.length })); } } // Commit transaction - console.debug('commitTransaction'); sqliteClient.commitTransaction(); }, { skipSyncCheck: true, // Skip sync check during upgrade to prevent loop @@ -156,14 +152,12 @@ const Upgrade: React.FC = () => { * Handle successful upgrade completion. */ onSuccess: () => { - console.debug('onSuccess'); void handleUpgradeSuccess(); }, /** * Handle upgrade error. */ onError: (error: Error) => { - console.debug('onError'); console.error('Upgrade failed:', error); setError(error.message); } @@ -171,7 +165,7 @@ const Upgrade: React.FC = () => { console.debug('executeVaultMutation done?'); } catch (error) { console.error('Upgrade failed:', error); - setError(error instanceof Error ? error.message : 'An unknown error occurred during the upgrade. Please try again.'); + setError(error instanceof Error ? error.message : t('upgrade.alerts.unknownErrorDuringUpgrade')); } finally { setIsLoading(false); } @@ -229,7 +223,7 @@ const Upgrade: React.FC = () => {
- {syncStatus || 'Upgrading vault...'} + {syncStatus || t('upgrade.upgrading')}
)} @@ -242,10 +236,10 @@ const Upgrade: React.FC = () => { setShowSelfHostedWarning(false); void performUpgrade(); }} - title="Self-Hosted Server" - message="If you're using a self-hosted server, make sure to also update your self-hosted instance as otherwise logging in to the web client will stop working. Do you want to continue with the upgrade?" - confirmText="Continue" - cancelText="Cancel" + title={t('upgrade.alerts.selfHostedServer')} + message={t('upgrade.alerts.selfHostedWarning')} + confirmText={t('upgrade.alerts.continueUpgrade')} + cancelText={t('upgrade.alerts.cancel')} /> {/* Version info modal */} @@ -253,8 +247,8 @@ const Upgrade: React.FC = () => { isOpen={showVersionInfo} onClose={() => setShowVersionInfo(false)} onConfirm={() => setShowVersionInfo(false)} - title="What's New" - message={`An upgrade is required to support the following changes:\n\n${latestVersion?.description ?? 'No description available for this version.'}`} + title={t('upgrade.whatsNew')} + message={`${t('upgrade.whatsNewDescription')}\n\n${latestVersion?.description ?? t('upgrade.noDescriptionAvailable')}`} />
@@ -280,33 +274,33 @@ const Upgrade: React.FC = () => { -

Upgrade Vault

+

{t('upgrade.title')}

- AliasVault has updated and your vault needs to be upgraded. This should only take a few seconds. + {t('upgrade.subtitle')}

- Version Information + {t('upgrade.versionInformation')}
- Your vault: + {t('upgrade.yourVault')} {currentVersion?.releaseVersion ?? '...'}
- New version: + {t('upgrade.newVersion')} {latestVersion?.releaseVersion ?? '...'} @@ -320,7 +314,7 @@ const Upgrade: React.FC = () => { type="button" onClick={handleUpgrade} > - {isLoading || isVaultMutationLoading ? (syncStatus || 'Upgrading...') : 'Upgrade Vault'} + {isLoading || isVaultMutationLoading ? (syncStatus || t('upgrade.upgrading')) : t('upgrade.upgrade')}
diff --git a/apps/browser-extension/src/i18n/locales/en.json b/apps/browser-extension/src/i18n/locales/en.json index d38c2b82b..1b356f25e 100644 --- a/apps/browser-extension/src/i18n/locales/en.json +++ b/apps/browser-extension/src/i18n/locales/en.json @@ -338,5 +338,38 @@ "clientUrlRequired": "Client URL is required", "clientUrlInvalid": "Please enter a valid client URL" } + }, + "upgrade": { + "title": "Upgrade Vault", + "subtitle": "AliasVault has updated and your vault needs to be upgraded. This should only take a few seconds.", + "versionInformation": "Version Information", + "yourVault": "Your vault:", + "newVersion": "New version:", + "upgrade": "Upgrade Vault", + "upgrading": "Upgrading...", + "logout": "Logout", + "whatsNew": "What's New", + "whatsNewDescription": "An upgrade is required to support the following changes:", + "noDescriptionAvailable": "No description available for this version.", + "okay": "Ok", + "status": { + "preparingUpgrade": "Preparing upgrade...", + "vaultAlreadyUpToDate": "Vault is already up to date", + "startingDatabaseTransaction": "Starting database transaction...", + "applyingDatabaseMigrations": "Applying database migrations...", + "applyingMigration": "Applying migration {{current}} of {{total}}...", + "committingChanges": "Committing changes..." + }, + "alerts": { + "error": "Error", + "unableToGetVersionInfo": "Unable to get version information. Please try again.", + "selfHostedServer": "Self-Hosted Server", + "selfHostedWarning": "If you're using a self-hosted server, make sure to also update your self-hosted instance as otherwise logging in to the web client will stop working.", + "cancel": "Cancel", + "continueUpgrade": "Continue Upgrade", + "upgradeFailed": "Upgrade Failed", + "failedToApplyMigration": "Failed to apply migration ({{current}} of {{total}})", + "unknownErrorDuringUpgrade": "An unknown error occurred during the upgrade. Please try again." + } } } \ No newline at end of file diff --git a/apps/mobile-app/app/(tabs)/emails/_layout.tsx b/apps/mobile-app/app/(tabs)/emails/_layout.tsx index 34c970b40..26d2a7cf4 100644 --- a/apps/mobile-app/app/(tabs)/emails/_layout.tsx +++ b/apps/mobile-app/app/(tabs)/emails/_layout.tsx @@ -1,4 +1,5 @@ import { Stack } from 'expo-router'; +import { useTranslation } from 'react-i18next'; import { Platform, Text } from 'react-native'; import { defaultHeaderOptions } from '@/components/themed/ThemedHeader'; @@ -8,12 +9,13 @@ import { AndroidHeader } from '@/components/ui/AndroidHeader'; * Emails layout. */ export default function EmailsLayout(): React.ReactNode { + const { t } = useTranslation(); return ( (null); @@ -73,11 +75,11 @@ function RootLayoutNav() : React.ReactNode { return; } - setStatus('Unlocking vault'); + setStatus(t('app.status.unlockingVault')); const isUnlocked = await dbContext.unlockVault(); if (isUnlocked) { await new Promise(resolve => setTimeout(resolve, 750)); - setStatus('Decrypting vault'); + setStatus(t('app.status.decryptingVault')); await new Promise(resolve => setTimeout(resolve, 750)); // Check if the vault is up to date, if not, redirect to the upgrade page. @@ -139,26 +141,26 @@ function RootLayoutNav() : React.ReactNode { */ onOffline: async () => { Alert.alert( - 'Sync Issue', - 'The AliasVault server could not be reached and your vault could not be synced. Would you like to open your local vault in read-only mode or retry the connection?', + t('app.alerts.syncIssue'), + t('app.alerts.syncIssueMessage'), [ { - text: 'Open Local Vault', + text: t('app.alerts.openLocalVault'), /** * Handle opening vault in read-only mode. */ onPress: async () : Promise => { - setStatus('Opening vault in read-only mode'); + setStatus(t('app.status.openingVaultReadOnly')); await handleVaultUnlock(); } }, { - text: 'Retry Sync', + text: t('app.alerts.retrySync'), /** * Handle retrying the connection. */ onPress: () : void => { - setStatus('Retrying connection...'); + setStatus(t('app.status.retryingConnection')); initialize(); } } @@ -170,7 +172,7 @@ function RootLayoutNav() : React.ReactNode { */ onError: async (error: string) => { // Show modal with error message - Alert.alert('Error', error); + Alert.alert(t('app.alerts.error'), error); // The logout user and navigate to the login screen. await webApi.logout(error); @@ -191,7 +193,7 @@ function RootLayoutNav() : React.ReactNode { }; initializeApp(); - }, [dbContext, syncVault, initializeAuth, webApi]); + }, [dbContext, syncVault, initializeAuth, webApi, t]); useEffect(() => { /** @@ -284,13 +286,13 @@ function RootLayoutNav() : React.ReactNode { }} > - + - + diff --git a/apps/mobile-app/app/reinitialize.tsx b/apps/mobile-app/app/reinitialize.tsx index a7bbbc3db..c9c38b9ee 100644 --- a/apps/mobile-app/app/reinitialize.tsx +++ b/apps/mobile-app/app/reinitialize.tsx @@ -1,5 +1,6 @@ import { Href, router } from 'expo-router'; import { useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { StyleSheet, View, Alert } from 'react-native'; import { useColors } from '@/hooks/useColorScheme'; @@ -23,6 +24,7 @@ export default function ReinitializeScreen() : React.ReactNode { const [status, setStatus] = useState(''); const hasInitialized = useRef(false); const colors = useColors(); + const { t } = useTranslation(); useEffect(() => { if (hasInitialized.current) { @@ -89,11 +91,11 @@ export default function ReinitializeScreen() : React.ReactNode { return; } - setStatus('Unlocking vault'); + setStatus(t('app.status.unlockingVault')); const isUnlocked = await dbContext.unlockVault(); if (isUnlocked) { await new Promise(resolve => setTimeout(resolve, 1000)); - setStatus('Decrypting vault'); + setStatus(t('app.status.decryptingVault')); await new Promise(resolve => setTimeout(resolve, 1000)); // Check if the vault is up to date, if not, redirect to the upgrade page. @@ -151,26 +153,26 @@ export default function ReinitializeScreen() : React.ReactNode { */ onOffline: () => { Alert.alert( - 'Sync Issue', - 'The AliasVault server could not be reached and your vault could not be synced. Would you like to open your local vault in read-only mode or retry the connection?', + t('app.alerts.syncIssue'), + t('app.alerts.syncIssueMessage'), [ { - text: 'Open Local Vault', + text: t('app.alerts.openLocalVault'), /** * Handle opening vault in read-only mode. */ onPress: async () : Promise => { - setStatus('Opening vault in read-only mode'); + setStatus(t('app.status.openingVaultReadOnly')); await handleVaultUnlock(); } }, { - text: 'Retry Sync', + text: t('app.alerts.retrySync'), /** * Handle retrying the connection. */ onPress: () : void => { - setStatus('Retrying connection...'); + setStatus(t('app.status.retryingConnection')); initialize(); } } @@ -187,7 +189,7 @@ export default function ReinitializeScreen() : React.ReactNode { }; initialize(); - }, [syncVault, authContext, dbContext]); + }, [syncVault, authContext, dbContext, t]); const styles = StyleSheet.create({ container: { @@ -212,8 +214,8 @@ export default function ReinitializeScreen() : React.ReactNode { return ( - Vault auto-locked after timeout. - Attempting to unlock. + {t('app.reinitialize.vaultAutoLockedMessage')} + {t('app.reinitialize.attemptingToUnlockMessage')} {status ? : null} diff --git a/apps/mobile-app/app/unlock.tsx b/apps/mobile-app/app/unlock.tsx index 59fbb50f2..ec9739bfb 100644 --- a/apps/mobile-app/app/unlock.tsx +++ b/apps/mobile-app/app/unlock.tsx @@ -269,7 +269,7 @@ export default function UnlockScreen() : React.ReactNode { {isLoading ? ( - + ) : ( (null); const [latestVersion, setLatestVersion] = useState(null); - const [upgradeStatus, setUpgradeStatus] = useState('Preparing upgrade...'); + const [upgradeStatus, setUpgradeStatus] = useState(''); const colors = useColors(); + const { t } = useTranslation(); const webApi = useWebApi(); const { executeVaultMutation, isLoading: isVaultMutationLoading, syncStatus } = useVaultMutate(); const { syncVault } = useVaultSync(); + // Initialize upgrade status with translation + useEffect(() => { + setUpgradeStatus(t('upgrade.status.preparingUpgrade')); + }, [t]); + /** * Load version information from the database. */ @@ -60,19 +67,19 @@ export default function UpgradeScreen() : React.ReactNode { */ const handleUpgrade = async (): Promise => { if (!sqliteClient || !currentVersion || !latestVersion) { - Alert.alert('Error', 'Unable to get version information. Please try again.'); + Alert.alert(t('upgrade.alerts.error'), t('upgrade.alerts.unableToGetVersionInfo')); return; } // Check if this is a self-hosted instance and show warning if needed if (await webApi.isSelfHosted()) { Alert.alert( - 'Self-Hosted Server', - "If you're using a self-hosted server, make sure to also update your self-hosted instance as otherwise logging in to the web client will stop working.", + t('upgrade.alerts.selfHostedServer'), + t('upgrade.alerts.selfHostedWarning'), [ - { text: 'Cancel', style: 'cancel' }, + { text: t('upgrade.alerts.cancel'), style: 'cancel' }, { - text: 'Continue Upgrade', + text: t('upgrade.alerts.continueUpgrade'), style: 'default', /** * Continue upgrade. @@ -93,26 +100,25 @@ export default function UpgradeScreen() : React.ReactNode { */ const performUpgrade = async (): Promise => { if (!sqliteClient || !currentVersion || !latestVersion) { - Alert.alert('Error', 'Unable to get version information. Please try again.'); + Alert.alert(t('upgrade.alerts.error'), t('upgrade.alerts.unableToGetVersionInfo')); return; } setIsLoading(true); - setUpgradeStatus('Preparing upgrade...'); + setUpgradeStatus(t('upgrade.status.preparingUpgrade')); try { // Get upgrade SQL commands from vault-sql shared library - setUpgradeStatus('Generating upgrade SQL...'); const vaultSqlGenerator = new VaultSqlGenerator(); const upgradeResult = vaultSqlGenerator.getUpgradeVaultSql(currentVersion.revision, latestVersion.revision); if (!upgradeResult.success) { - throw new Error(upgradeResult.error ?? 'Failed to generate upgrade SQL'); + throw new Error(upgradeResult.error ?? t('upgrade.alerts.upgradeFailed')); } if (upgradeResult.sqlCommands.length === 0) { // No upgrade needed, vault is already up to date - setUpgradeStatus('Vault is already up to date'); + setUpgradeStatus(t('upgrade.status.vaultAlreadyUpToDate')); await new Promise(resolve => setTimeout(resolve, 1000)); await handleUpgradeSuccess(); return; @@ -121,26 +127,26 @@ export default function UpgradeScreen() : React.ReactNode { // Use the useVaultMutate hook to handle the upgrade and vault upload await executeVaultMutation(async () => { // Begin transaction - setUpgradeStatus('Starting database transaction...'); + setUpgradeStatus(t('upgrade.status.startingDatabaseTransaction')); await NativeVaultManager.beginTransaction(); // Execute each SQL command - setUpgradeStatus('Applying database migrations...'); + setUpgradeStatus(t('upgrade.status.applyingDatabaseMigrations')); for (let i = 0; i < upgradeResult.sqlCommands.length; i++) { const sqlCommand = upgradeResult.sqlCommands[i]; - setUpgradeStatus(`Applying migration ${i + 1} of ${upgradeResult.sqlCommands.length}...`); + setUpgradeStatus(t('upgrade.status.applyingMigration', { current: i + 1, total: upgradeResult.sqlCommands.length })); try { await NativeVaultManager.executeRaw(sqlCommand); } catch (error) { console.error(`Error executing SQL command ${i + 1}:`, sqlCommand, error); await NativeVaultManager.rollbackTransaction(); - throw new Error(`Failed to apply migration (${i + 1} of ${upgradeResult.sqlCommands.length})`); + throw new Error(t('upgrade.alerts.failedToApplyMigration', { current: i + 1, total: upgradeResult.sqlCommands.length })); } } // Commit transaction - setUpgradeStatus('Committing changes...'); + setUpgradeStatus(t('upgrade.status.committingChanges')); await NativeVaultManager.commitTransaction(); }, { skipSyncCheck: true, // Skip sync check during upgrade to prevent loop @@ -155,16 +161,16 @@ export default function UpgradeScreen() : React.ReactNode { */ onError: (error: Error) => { console.error('Upgrade failed:', error); - Alert.alert('Upgrade Failed', error.message); + Alert.alert(t('upgrade.alerts.upgradeFailed'), error.message); } }); } catch (error) { console.error('Upgrade failed:', error); - Alert.alert('Upgrade Failed', error instanceof Error ? error.message : 'An unknown error occurred during the upgrade. Please try again.'); + Alert.alert(t('upgrade.alerts.upgradeFailed'), error instanceof Error ? error.message : t('upgrade.alerts.unknownErrorDuringUpgrade')); } finally { setIsLoading(false); - setUpgradeStatus('Preparing upgrade...'); + setUpgradeStatus(t('upgrade.status.preparingUpgrade')); } }; @@ -219,10 +225,10 @@ export default function UpgradeScreen() : React.ReactNode { */ const showVersionDialog = (): void => { Alert.alert( - "What's New", - `An upgrade is required to support the following changes:\n\n${latestVersion?.description ?? 'No description available for this version.'}`, + t('upgrade.whatsNew'), + `${t('upgrade.whatsNewDescription')}\n\n${latestVersion?.description ?? t('upgrade.noDescriptionAvailable')}`, [ - { text: 'Okay', style: 'default' } + { text: t('upgrade.okay'), style: 'default' } ] ); }; @@ -399,7 +405,7 @@ export default function UpgradeScreen() : React.ReactNode { - Upgrade Vault + {t('upgrade.title')} @@ -407,10 +413,10 @@ export default function UpgradeScreen() : React.ReactNode { {username} - AliasVault has updated and your vault needs to be upgraded. This should only take a few seconds. + {t('upgrade.subtitle')} - Version Information + {t('upgrade.versionInformation')} - Your vault: + {t('upgrade.yourVault')} {currentVersion?.releaseVersion ?? '...'} - New version: + {t('upgrade.newVersion')} {latestVersion?.releaseVersion ?? '...'} @@ -438,7 +444,7 @@ export default function UpgradeScreen() : React.ReactNode { disabled={isLoading || isVaultMutationLoading} > - {isLoading || isVaultMutationLoading ? (syncStatus || 'Upgrading...') : 'Upgrade'} + {isLoading || isVaultMutationLoading ? (syncStatus || t('upgrade.upgrading')) : t('upgrade.upgrade')} @@ -446,7 +452,7 @@ export default function UpgradeScreen() : React.ReactNode { style={styles.logoutButton} onPress={handleLogout} > - Logout + {t('upgrade.logout')} diff --git a/apps/mobile-app/i18n/locales/en.json b/apps/mobile-app/i18n/locales/en.json index bed80b328..f63dab234 100644 --- a/apps/mobile-app/i18n/locales/en.json +++ b/apps/mobile-app/i18n/locales/en.json @@ -23,7 +23,6 @@ "authCode": "Authentication Code", "unlock": "Unlock", "unlocking": "Unlocking...", - "unlockingVault": "Unlocking vault", "loggingIn": "Logging in", "validatingCredentials": "Validating credentials", "syncingVault": "Syncing vault", @@ -354,5 +353,61 @@ "VAULT_NOT_UP_TO_DATE": "Your vault is not up-to-date. Please synchronize your vault and try again.", "INTERNAL_SERVER_ERROR": "Internal server error.", "VAULT_ERROR": "The local vault is not up-to-date. Please synchronize your vault by refreshing the page and try again." + }, + "app": { + "status": { + "unlockingVault": "Unlocking vault", + "decryptingVault": "Decrypting vault", + "openingVaultReadOnly": "Opening vault in read-only mode", + "retryingConnection": "Retrying connection..." + }, + "alerts": { + "syncIssue": "Sync Issue", + "syncIssueMessage": "The AliasVault server could not be reached and your vault could not be synced. Would you like to open your local vault in read-only mode or retry the connection?", + "openLocalVault": "Open Local Vault", + "retrySync": "Retry Sync", + "error": "Error" + }, + "navigation": { + "login": "Login", + "notFound": "Not Found" + }, + "reinitialize": { + "vaultAutoLockedMessage": "Vault auto-locked after timeout.", + "attemptingToUnlockMessage": "Attempting to unlock." + } + }, + "upgrade": { + "title": "Upgrade Vault", + "subtitle": "AliasVault has updated and your vault needs to be upgraded. This should only take a few seconds.", + "versionInformation": "Version Information", + "yourVault": "Your vault:", + "newVersion": "New version:", + "upgrade": "Upgrade", + "upgrading": "Upgrading...", + "logout": "Logout", + "whatsNew": "What's New", + "whatsNewDescription": "An upgrade is required to support the following changes:", + "noDescriptionAvailable": "No description available for this version.", + "okay": "Ok", + "status": { + "preparingUpgrade": "Preparing upgrade...", + "vaultAlreadyUpToDate": "Vault is already up to date", + "startingDatabaseTransaction": "Starting database transaction...", + "applyingDatabaseMigrations": "Applying database migrations...", + "applyingMigration": "Applying migration {{current}} of {{total}}...", + "committingChanges": "Committing changes..." + }, + "alerts": { + "error": "Error", + "unableToGetVersionInfo": "Unable to get version information. Please try again.", + "selfHostedServer": "Self-Hosted Server", + "selfHostedWarning": "If you're using a self-hosted server, make sure to also update your self-hosted instance as otherwise logging in to the web client will stop working.", + "cancel": "Cancel", + "continueUpgrade": "Continue Upgrade", + "upgradeFailed": "Upgrade Failed", + "failedToApplyMigration": "Failed to apply migration ({{current}} of {{total}})", + "unknownErrorDuringUpgrade": "An unknown error occurred during the upgrade. Please try again." + } } } \ No newline at end of file