Cleanup mobile app translations to use new item.* based keys (#1468)

This commit is contained in:
Leendert de Borst
2026-01-21 11:12:40 +01:00
committed by Leendert de Borst
parent 970ceb9423
commit a14142a45a
17 changed files with 56 additions and 73 deletions

View File

@@ -104,13 +104,13 @@ export default function AutofillCredentialCreatedScreen() : React.ReactNode {
/>
</View>
<ThemedText style={styles.title}>{t('credentials.credentialCreated')}</ThemedText>
<ThemedText style={styles.title}>{t('items.itemCreated')}</ThemedText>
<ThemedText style={styles.message}>
{t('credentials.credentialCreatedMessage')}
{t('items.itemCreatedMessage')}
</ThemedText>
<ThemedText style={[styles.message, styles.boldMessage]}>
{t('credentials.switchBackToBrowser')}
{t('items.switchBackToBrowser')}
</ThemedText>
</ThemedView>
</ThemedSafeAreaView>

View File

@@ -337,7 +337,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
<View style={styles.settingsContainer}>
<View style={styles.sliderContainer}>
<View style={styles.sliderHeader}>
<ThemedText style={styles.sliderLabel}>{t('credentials.passwordLength')}</ThemedText>
<ThemedText style={styles.sliderLabel}>{t('items.passwordLength')}</ThemedText>
<ThemedText style={styles.sliderValue}>{sliderValue ?? 0}</ThemedText>
</View>
<Slider
@@ -358,7 +358,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
<View style={styles.settingsContainer}>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeLowercase')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeLowercase')}</ThemedText>
<Switch
value={settings.UseLowercase}
onValueChange={(value) => updateSetting('UseLowercase', value)}
@@ -368,7 +368,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeUppercase')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeUppercase')}</ThemedText>
<Switch
value={settings.UseUppercase}
onValueChange={(value) => updateSetting('UseUppercase', value)}
@@ -378,7 +378,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeNumbers')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeNumbers')}</ThemedText>
<Switch
value={settings.UseNumbers}
onValueChange={(value) => updateSetting('UseNumbers', value)}
@@ -388,7 +388,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeSpecialChars')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeSpecialChars')}</ThemedText>
<Switch
value={settings.UseSpecialChars}
onValueChange={(value) => updateSetting('UseSpecialChars', value)}
@@ -398,7 +398,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode {
</View>
<View style={[styles.settingItem, styles.settingItemLast]}>
<ThemedText style={styles.settingLabel}>{t('credentials.avoidAmbiguousChars')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.avoidAmbiguousChars')}</ThemedText>
<Switch
value={settings.UseNonAmbiguousChars}
onValueChange={(value) => updateSetting('UseNonAmbiguousChars', value)}

View File

@@ -340,7 +340,7 @@ export default function VaultUnlockSettingsScreen() : React.ReactNode {
<View style={[styles.option, styles.optionLast]}>
<View style={styles.optionHeader}>
<ThemedText style={styles.optionText}>{t('credentials.password')}</ThemedText>
<ThemedText style={styles.optionText}>{t('items.password')}</ThemedText>
<Switch
value={true}
disabled={true}

View File

@@ -427,7 +427,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
<View style={styles.sliderContainer}>
<View style={styles.sliderHeader}>
<ThemedText style={styles.sliderLabel}>{t('credentials.passwordLength')}</ThemedText>
<ThemedText style={styles.sliderLabel}>{t('items.passwordLength')}</ThemedText>
<View style={styles.sliderValueContainer}>
<ThemedText style={styles.sliderValue}>{sliderValue}</ThemedText>
<TouchableOpacity
@@ -464,7 +464,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<View style={styles.modalHeader}>
<ThemedText style={styles.modalTitle}>{t('credentials.changePasswordComplexity')}</ThemedText>
<ThemedText style={styles.modalTitle}>{t('items.changePasswordComplexity')}</ThemedText>
<TouchableOpacity
style={styles.closeButton}
onPress={() => setShowSettingsModal(false)}
@@ -494,7 +494,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
<View style={styles.settingsSection}>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeLowercase')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeLowercase')}</ThemedText>
<Switch
value={currentSettings?.UseLowercase ?? true}
onValueChange={(settingValue) => updateSetting('UseLowercase', settingValue)}
@@ -504,7 +504,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeUppercase')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeUppercase')}</ThemedText>
<Switch
value={currentSettings?.UseUppercase ?? true}
onValueChange={(settingValue) => updateSetting('UseUppercase', settingValue)}
@@ -514,7 +514,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeNumbers')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeNumbers')}</ThemedText>
<Switch
value={currentSettings?.UseNumbers ?? true}
onValueChange={(settingValue) => updateSetting('UseNumbers', settingValue)}
@@ -524,7 +524,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.includeSpecialChars')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.includeSpecialChars')}</ThemedText>
<Switch
value={currentSettings?.UseSpecialChars ?? true}
onValueChange={(settingValue) => updateSetting('UseSpecialChars', settingValue)}
@@ -534,7 +534,7 @@ const AdvancedPasswordFieldComponent = forwardRef<AdvancedPasswordFieldRef, Adva
</View>
<View style={styles.settingItem}>
<ThemedText style={styles.settingLabel}>{t('credentials.avoidAmbiguousChars')}</ThemedText>
<ThemedText style={styles.settingLabel}>{t('items.avoidAmbiguousChars')}</ThemedText>
<Switch
value={currentSettings?.UseNonAmbiguousChars ?? false}
onValueChange={(settingValue) => updateSetting('UseNonAmbiguousChars', settingValue)}

View File

@@ -367,7 +367,7 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
style={styles.textInput}
value={isCustomDomain ? value : localPart}
onChangeText={handleLocalPartChange}
placeholder={isCustomDomain ? t('credentials.enterFullEmail') : t('credentials.enterEmailPrefix')}
placeholder={isCustomDomain ? t('items.enterFullEmail') : t('items.enterEmailPrefix')}
placeholderTextColor={colors.textMuted}
autoCapitalize="none"
autoCorrect={false}
@@ -394,8 +394,8 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
<TouchableOpacity style={styles.toggleButton} onPress={toggleCustomDomain}>
<Text style={styles.toggleButtonText}>
{isCustomDomain
? t('credentials.useDomainChooser')
: t('credentials.enterCustomDomain')}
? t('items.useDomainChooser')
: t('items.enterCustomDomain')}
</Text>
</TouchableOpacity>
@@ -412,7 +412,7 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
<Pressable style={styles.modalContent} onPress={(e) => e.stopPropagation()}>
<View style={styles.modalHeader}>
<ThemedText style={styles.modalTitle}>
{t('credentials.selectEmailDomain')}
{t('items.selectEmailDomain')}
</ThemedText>
<TouchableOpacity
style={styles.modalCloseButton}
@@ -427,14 +427,14 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
<View style={styles.domainSection}>
<View style={styles.domainSectionHeader}>
<Text style={styles.domainSectionTitle}>
{t('credentials.privateEmailTitle')}
{t('items.privateEmailTitle')}
</Text>
<Text style={styles.domainSectionSubtitle}>
({t('credentials.privateEmailAliasVaultServer')})
({t('items.privateEmailAliasVaultServer')})
</Text>
</View>
<Text style={styles.domainSectionDescription}>
{t('credentials.privateEmailDescription')}
{t('items.privateEmailDescription')}
</Text>
<View style={styles.domainList}>
{privateEmailDomains.filter(domain => !hiddenPrivateEmailDomains.includes(domain)).map((domain) => (
@@ -462,10 +462,10 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
<View style={styles.domainSection}>
<Text style={styles.domainSectionTitle}>
{t('credentials.publicEmailTitle')}
{t('items.publicEmailTitle')}
</Text>
<Text style={styles.domainSectionDescription}>
{t('credentials.publicEmailDescription')}
{t('items.publicEmailDescription')}
</Text>
<View style={styles.domainList}>
{PUBLIC_EMAIL_DOMAINS.map((domain) => (

View File

@@ -273,7 +273,7 @@ export function ItemCard({ item, onItemDelete }: ItemCardProps): React.ReactNode
return (
<ContextMenu
title={t('credentials.contextMenu.title')}
title={t('items.contextMenu.title')}
actions={getMenuActions()}
onPress={handleContextMenuAction}
previewBackgroundColor={colors.accentBackground}

View File

@@ -67,7 +67,7 @@ export function ServiceUrlNotice({ serviceUrl, onDismiss }: IServiceUrlNoticePro
>
<MaterialIcons name="add-circle" size={20} color={colors.primary} />
<ThemedText style={styles.text}>
{t('credentials.createNewAliasFor')} &ldquo;{serviceName}&rdquo;?
{t('items.createNewAliasFor')} &ldquo;{serviceName}&rdquo;?
</ThemedText>
</TouchableOpacity>
<TouchableOpacity

View File

@@ -30,28 +30,28 @@ export const AliasDetails: React.FC<AliasDetailsProps> = ({ item }) : React.Reac
return (
<ThemedView style={styles.section}>
<ThemedText type="subtitle">{t('credentials.alias')}</ThemedText>
<ThemedText type="subtitle">{t('items.alias')}</ThemedText>
{hasName && (
<FormInputCopyToClipboard
label={t('credentials.fullName')}
label={t('items.fullName')}
value={fullName}
/>
)}
{firstName && (
<FormInputCopyToClipboard
label={t('credentials.firstName')}
label={t('items.firstName')}
value={firstName}
/>
)}
{lastName && (
<FormInputCopyToClipboard
label={t('credentials.lastName')}
label={t('items.lastName')}
value={lastName}
/>
)}
{IdentityHelperUtils.isValidBirthDate(birthDate) && (
<FormInputCopyToClipboard
label={t('credentials.birthDate')}
label={t('items.birthDate')}
value={IdentityHelperUtils.normalizeBirthDate(birthDate!)}
/>
)}

View File

@@ -107,7 +107,7 @@ export const AttachmentSection: React.FC<AttachmentSectionProps> = ({ item }): R
} else {
Alert.alert(
t('common.success'),
`${t('credentials.fileSavedTo')}: ${filePath}`
`${t('items.fileSavedTo')}: ${filePath}`
);
}
} catch (error) {
@@ -236,7 +236,7 @@ export const AttachmentSection: React.FC<AttachmentSectionProps> = ({ item }): R
return (
<ThemedView style={styles.container}>
<ThemedText type="subtitle">
{t('credentials.attachments')}
{t('items.attachments')}
</ThemedText>
{attachments.map(attachment => (
<TouchableOpacity

View File

@@ -229,7 +229,7 @@ export const AttachmentUploader: React.FC<AttachmentUploaderProps> = ({
onPress={() => deleteAttachment(attachment)}
>
<ThemedText style={styles.deleteButtonText}>
{t('credentials.deleteAttachment')}
{t('items.deleteAttachment')}
</ThemedText>
</TouchableOpacity>
</View>

View File

@@ -148,7 +148,7 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
});
if (!response.ok) {
setError(t('credentials.emailLoadError'));
setError(t('items.emailLoadError'));
return;
}
@@ -208,12 +208,12 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return;
}
} catch {
setError(t('credentials.emailLoadError'));
setError(t('items.emailLoadError'));
}
}
} catch (err) {
console.error('Error loading emails:', err);
setError(t('credentials.emailUnexpectedError'));
setError(t('items.emailUnexpectedError'));
} finally {
setLoading(false);
}
@@ -310,7 +310,7 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return (
<ThemedView style={styles.section}>
<View style={styles.titleContainer}>
<ThemedText type="title" style={styles.title}>{t('credentials.recentEmails')}</ThemedText>
<ThemedText type="title" style={styles.title}>{t('items.recentEmails')}</ThemedText>
</View>
<View style={styles.errorContainer}>
<ThemedText style={styles.errorText}>{error}</ThemedText>
@@ -323,10 +323,10 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return (
<ThemedView style={styles.section}>
<View style={styles.titleContainer}>
<ThemedText type="title" style={styles.title}>{t('credentials.recentEmails')}</ThemedText>
<ThemedText type="title" style={styles.title}>{t('items.recentEmails')}</ThemedText>
<PulseDot />
</View>
<ThemedText style={styles.placeholderText}>{t('credentials.loadingEmails')}</ThemedText>
<ThemedText style={styles.placeholderText}>{t('items.loadingEmails')}</ThemedText>
</ThemedView>
);
}
@@ -335,9 +335,9 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return (
<ThemedView style={styles.section}>
<View style={styles.titleContainer}>
<ThemedText type="title" style={styles.title}>{t('credentials.recentEmails')}</ThemedText>
<ThemedText type="title" style={styles.title}>{t('items.recentEmails')}</ThemedText>
</View>
<ThemedText style={styles.placeholderText}>{t('credentials.offlineEmailsMessage')}</ThemedText>
<ThemedText style={styles.placeholderText}>{t('items.offlineEmailsMessage')}</ThemedText>
</ThemedView>
);
}
@@ -346,10 +346,10 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return (
<ThemedView style={styles.section}>
<View style={styles.titleContainer}>
<ThemedText type="title" style={styles.title}>{t('credentials.recentEmails')}</ThemedText>
<ThemedText type="title" style={styles.title}>{t('items.recentEmails')}</ThemedText>
<PulseDot />
</View>
<ThemedText style={styles.placeholderText}>{t('credentials.noEmailsYet')}</ThemedText>
<ThemedText style={styles.placeholderText}>{t('items.noEmailsYet')}</ThemedText>
</ThemedView>
);
}
@@ -357,7 +357,7 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) : React.Rea
return (
<ThemedView style={styles.section}>
<View style={styles.titleContainer}>
<ThemedText type="title" style={styles.title}>{t('credentials.recentEmails')}</ThemedText>
<ThemedText type="title" style={styles.title}>{t('items.recentEmails')}</ThemedText>
<PulseDot />
</View>
{displayedEmails.map((mail) => (

View File

@@ -116,7 +116,7 @@ export const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
} else {
Alert.alert(
t('common.success'),
`${t('credentials.fileSavedTo')}: ${filePath}`
`${t('items.fileSavedTo')}: ${filePath}`
);
}
} catch (error) {
@@ -252,10 +252,10 @@ export const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
<View style={styles.unsupportedContainer}>
<Ionicons name="document-outline" size={80} color={colors.text} />
<ThemedText style={styles.unsupportedText}>
{t('credentials.previewNotSupported')}
{t('items.previewNotSupported')}
</ThemedText>
<ThemedText style={styles.unsupportedSubtext}>
{t('credentials.downloadToView')}
{t('items.downloadToView')}
</ThemedText>
</View>
);

View File

@@ -94,7 +94,7 @@ export const LoginFields: React.FC<LoginFieldsProps> = ({ item }) : React.ReactN
return (
<ThemedView style={styles.section}>
<ThemedText type="subtitle">{t('credentials.loginCredentials')}</ThemedText>
<ThemedText type="subtitle">{t('items.loginCredentials')}</ThemedText>
{/* Render login fields using FieldBlock */}
{sortedLoginFields.map((field: ItemField) => (

View File

@@ -107,7 +107,7 @@ export const NotesSection: React.FC<NotesSectionProps> = ({ item }) : React.Reac
return (
<ThemedView style={styles.section}>
<ThemedText type="subtitle">{t('credentials.notes')}</ThemedText>
<ThemedText type="subtitle">{t('items.notes')}</ThemedText>
<View style={styles.notesContainer}>
{parts.map((part, index) => {
if (part.type === 'url') {

View File

@@ -205,7 +205,7 @@ export const TotpSection: React.FC<TotpSectionProps> = ({ item }) : React.ReactN
<View style={styles.codeContainer}>
<View>
<ThemedText style={styles.label}>
{t('credentials.totpCode')}
{t('items.totpCode')}
</ThemedText>
<ThemedText style={styles.code}>
{currentCodes[totpCode.Id]}

View File

@@ -322,10 +322,10 @@ export const AuthProvider: React.FC<{
}
// Fallback to password
return 'credentials.password';
return 'items.password';
} catch (error) {
console.error('Failed to get auth method display key:', error);
return 'credentials.password';
return 'items.password';
}
}, [getEnabledAuthMethods, getBiometricDisplayName, isBiometricsEnabledOnDevice]);

View File

@@ -209,8 +209,6 @@
},
"passkeys": {
"passkey": "Passkey",
"site": "Site",
"displayName": "Display Name",
"helpText": "Passkeys are created on the website when prompted. They cannot be manually edited. To remove this passkey, you can delete it from this credential.",
"passkeyMarkedForDeletion": "Passkey marked for deletion",
"passkeyWillBeDeleted": "This passkey will be deleted when you save this credential."
@@ -317,13 +315,6 @@
"pinDescription": "Use a custom PIN code to unlock your vault more quickly.",
"pinEnabled": "PIN unlock enabled successfully",
"pinDisabled": "PIN unlock has been disabled",
"setupPin": "Setup PIN",
"enterNewPin": "Enter New PIN",
"enterNewPinDescription": "Choose a PIN to unlock your vault",
"confirmPin": "Confirm PIN",
"confirmPinDescription": "Re-enter your PIN to confirm",
"pinMismatch": "PINs do not match. Please try again.",
"pinLocked": "PIN locked after too many failed attempts. Please use your master password.",
"passwordHelp": "Re-enter your full master password to unlock your vault. This is always enabled as fallback option.",
"keystoreIOS": "iOS Keychain",
"keystoreAndroid": "Android Keystore"
@@ -421,23 +412,16 @@
"qrScanner": {
"title": "QR Code Scanner",
"scanningMessage": "Scan AliasVault QR code",
"invalidQrCode": "Invalid QR Code",
"notAliasVaultQr": "This is not a valid AliasVault QR code. Please scan a QR code generated by AliasVault.",
"cameraPermissionTitle": "Camera Permission Required",
"cameraPermissionMessage": "Please allow camera access to scan QR codes.",
"mobileLogin": {
"confirmTitle": "Confirm Login Request",
"confirmSubtitle": "Re-authenticate to approve login on another device.",
"confirmMessage": "You are about to log in on a remote device with your account. This other device will have full access to your vault. Only proceed if you trust this device.",
"successDescription": "The remote device has been successfully logged in.",
"requestExpired": "This login request has expired. Please generate a new QR code.",
"authenticationFailed": "Authentication failed. Please try again.",
"noAuthMethodEnabled": "Biometric or PIN unlock needs to be enabled to unlock with mobile"
}
}
},
"navigation": {
"credentials": "Credentials",
"vault": "Vault",
"emails": "Emails",
"settings": "Settings"
@@ -499,12 +483,11 @@
"deleteItem": "Delete Item",
"itemDetails": "Item Details",
"itemCreated": "Item Created",
"itemCreatedMessage": "Your new item has been added to your vault and is ready to use.",
"emailPreview": "Email Preview",
"untitled": "Untitled",
"name": "Name",
"namePlaceholder": "e.g., Google, Amazon",
"url": "URL",
"urlPlaceholder": "e.g., https://google.com",
"service": "Service",
"serviceName": "Service Name",
"serviceUrl": "Service URL",